@justeattakeaway/pie-webc-core 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +2 -0
- package/.turbo/turbo-build.log +3 -3
- package/CHANGELOG.md +8 -0
- package/README.md +68 -1
- package/dist/index.js +35 -23
- package/package.json +6 -1
- package/playwright/index.html +56 -0
- package/playwright/index.ts +1 -0
- package/playwright-lit.config.ts +18 -0
- package/src/mixins/formControl/formControlMixin.ts +58 -0
- package/src/mixins/index.ts +4 -0
- package/src/mixins/rtl/rtlMixin.ts +5 -12
- package/src/mixins/types/GenericConstructor.ts +7 -0
- package/src/mixins/types/LitElementMixin.ts +7 -0
- package/src/{decorators/test → test/decorators}/required-property.spec.ts +1 -1
- package/src/{decorators/test → test/decorators}/valid-property-values.spec.ts +1 -1
- package/src/{functions/test → test/functions}/defineCustomElement.spec.ts +1 -1
- package/src/test/mixins/formControlMixin/MockComponent.ts +19 -0
- package/src/test/mixins/formControlMixin/formControlMixin.browser.spec.ts +76 -0
- package/src/{mixins/test → test/mixins/rtlMixin}/rtlMixin.client.spec.ts +1 -1
- package/src/{mixins/test → test/mixins/rtlMixin}/rtlMixin.server.spec.ts +1 -1
- package/tsconfig.json +4 -26
- package/vite.config.js +1 -0
package/.eslintignore
CHANGED
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[36mvite v4.3.9 [32mbuilding for production...[36m[39m
|
|
2
2
|
transforming...
|
|
3
|
-
[32m✓[39m
|
|
3
|
+
[32m✓[39m 11 modules transformed.
|
|
4
4
|
rendering chunks...
|
|
5
5
|
computing gzip size...
|
|
6
|
-
[2mdist/[22m[36mindex.js [39m[1m[
|
|
7
|
-
[32m✓ built in
|
|
6
|
+
[2mdist/[22m[36mindex.js [39m[1m[2m2.23 kB[22m[1m[22m[2m │ gzip: 1.02 kB[22m
|
|
7
|
+
[32m✓ built in 117ms[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.14.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [Added] - Form Control Mixin for adding native form association behaviour to web components ([#1142](https://github.com/justeattakeaway/pie/pull/1142)) by [@jamieomaguire](https://github.com/jamieomaguire)
|
|
8
|
+
|
|
9
|
+
- [Changed] - Re organised test structure and added playwright testing ([#1142](https://github.com/justeattakeaway/pie/pull/1142)) by [@jamieomaguire](https://github.com/jamieomaguire)
|
|
10
|
+
|
|
3
11
|
## 0.13.0
|
|
4
12
|
|
|
5
13
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -2,6 +2,73 @@
|
|
|
2
2
|
<img align="center" src="../../../readme_image.png" height="200" alt="">
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://www.npmjs.com/@justeattakeaway/pie-webc-core">
|
|
7
|
+
<img alt="GitHub Workflow Status" src="https://img.shields.io/npm/v/@justeattakeaway/pie-webc-core.svg">
|
|
8
|
+
</a>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
5
11
|
# pie-webc-core
|
|
6
12
|
|
|
7
|
-
|
|
13
|
+
1. [Introduction](#introduction)
|
|
14
|
+
2. [Installation](#installation)
|
|
15
|
+
3. [Importing the package](#importing-the-package)
|
|
16
|
+
4. [Dependencies](#dependencies)
|
|
17
|
+
5. [Contributing](#contributing)
|
|
18
|
+
6. [Testing](#testing)
|
|
19
|
+
|
|
20
|
+
## Introduction
|
|
21
|
+
|
|
22
|
+
A core library for PIE web components which contains classes, mixins, utilities and anything other functionality that can be shared across web components.
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
To add `pie-webc-core` to your component, run the following on your command line:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
$ yarn add @justeattakeaway/pie-webc-core
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Importing the package
|
|
34
|
+
|
|
35
|
+
```js
|
|
36
|
+
import { RequiredProperty, RtlMixin } from '@justeattakeaway/pie-webc-core';
|
|
37
|
+
|
|
38
|
+
export class MyComponent extends RtlMixin(LitElement) implements MyComponentProps {
|
|
39
|
+
// ...
|
|
40
|
+
|
|
41
|
+
@property({ type: String })
|
|
42
|
+
@requiredProperty('my-component')
|
|
43
|
+
public value!: string;
|
|
44
|
+
|
|
45
|
+
// ...
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Dependencies
|
|
50
|
+
|
|
51
|
+
This package provides `lit` as a dependency which means the package that depends on `@justeattakeaway/pie-webc-core` will automatically install `lit` into the `node_modules` folder of its consuming application.
|
|
52
|
+
|
|
53
|
+
Other dependencies may be added in future to make it easier for people to install and use our components.
|
|
54
|
+
|
|
55
|
+
## Contributing
|
|
56
|
+
|
|
57
|
+
Check out our [contributing guide](https://github.com/justeattakeaway/pie/wiki/Contributing-Guide) for more information on [local development](https://github.com/justeattakeaway/pie/wiki/Contributing-Guide#local-development).
|
|
58
|
+
|
|
59
|
+
To run the unit tests, simply run `yarn test --filter=pie-webc-core` from the root of the monorepo.
|
|
60
|
+
|
|
61
|
+
## Testing
|
|
62
|
+
|
|
63
|
+
- Currently we have two methods of testing our core utilities:
|
|
64
|
+
- Unit tests using Vitest
|
|
65
|
+
- Browser tests using Playwright
|
|
66
|
+
|
|
67
|
+
### Unit tests
|
|
68
|
+
We write unit tests for small pieces of functionality that can be tested in isolation. These could be things such as class decorators or utility functions. However, sometimes testing in an isolated node environment is not enough. This is where Browser tests come in.
|
|
69
|
+
|
|
70
|
+
### Browser tests
|
|
71
|
+
We write browser tests for functionality that requires a browser environment to test. This could be things such as component class mixins. For these, we run our tests using Playwright. This allows us to run our tests in a real browser environment and test things such as DOM manipulation and events. A useful pattern for this kind of testing is to write a mock component that uses the mixin you want to test. This allows you to test the mixin in isolation without having to worry about the implementation of the component itself.
|
|
72
|
+
|
|
73
|
+
### Naming and running tests
|
|
74
|
+
Currently, for writing unit tests we simply name the file `**/*.spec.ts`. To write browser tests, we name the file `**/*.browser.spec.ts`. This allows us to run all unit tests using `yarn test --filter=pie-webc-core` and all browser tests using `yarn test:browsers --filter=pie-webc-core`.
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isServer as u } from "lit";
|
|
2
|
-
const
|
|
3
|
-
class
|
|
2
|
+
const l = (e) => {
|
|
3
|
+
class t extends e {
|
|
4
4
|
/**
|
|
5
5
|
* A getter to determine whether the text direction is right-to-left (RTL).
|
|
6
6
|
* If the `dir` property is present on the component, it will be used to determine the text direction.
|
|
@@ -14,40 +14,52 @@ const f = (e) => {
|
|
|
14
14
|
return this.dir ? this.dir === "rtl" : !u && !this.dir ? document.documentElement.getAttribute("dir") === "rtl" : !1;
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
return
|
|
18
|
-
},
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
return t;
|
|
18
|
+
}, a = (e) => {
|
|
19
|
+
class t extends e {
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21
|
+
constructor(...i) {
|
|
22
|
+
super(...i), this._internals = this.attachInternals();
|
|
23
|
+
}
|
|
24
|
+
get form() {
|
|
25
|
+
return this._internals.form;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return t.formAssociated = !0, t;
|
|
29
|
+
}, f = (e, t, n) => function(o, r) {
|
|
30
|
+
const s = `#${r}`;
|
|
31
|
+
Object.defineProperty(o, r, {
|
|
21
32
|
get() {
|
|
22
33
|
return this[s];
|
|
23
34
|
},
|
|
24
|
-
set(
|
|
25
|
-
|
|
26
|
-
`<${e}> Invalid value "${
|
|
27
|
-
`Must be one of: ${
|
|
28
|
-
`Falling back to default value: "${
|
|
29
|
-
), this[s] =
|
|
35
|
+
set(c) {
|
|
36
|
+
t.includes(c) ? this[s] = c : (console.error(
|
|
37
|
+
`<${e}> Invalid value "${c}" provided for property "${r}".`,
|
|
38
|
+
`Must be one of: ${t.join(" | ")}.`,
|
|
39
|
+
`Falling back to default value: "${n}"`
|
|
40
|
+
), this[s] = n);
|
|
30
41
|
},
|
|
31
42
|
configurable: !0
|
|
32
43
|
});
|
|
33
|
-
},
|
|
34
|
-
const o = `#${
|
|
35
|
-
Object.defineProperty(
|
|
44
|
+
}, m = (e) => function(n, i) {
|
|
45
|
+
const o = `#${i}`;
|
|
46
|
+
Object.defineProperty(n, i, {
|
|
36
47
|
get() {
|
|
37
48
|
return this[o];
|
|
38
49
|
},
|
|
39
|
-
set(
|
|
40
|
-
(
|
|
50
|
+
set(r) {
|
|
51
|
+
(r == null || typeof r == "string" && r.trim() === "") && console.error(`<${e}> Missing required attribute "${i}"`), this[o] = r;
|
|
41
52
|
},
|
|
42
53
|
configurable: !0
|
|
43
54
|
});
|
|
44
55
|
};
|
|
45
|
-
function
|
|
46
|
-
customElements.get(e) ? console.warn(`PIE Web Component: "${e}" has already been defined. Please ensure the component is only being defined once in your application.`) : customElements.define(e,
|
|
56
|
+
function h(e, t) {
|
|
57
|
+
customElements.get(e) ? console.warn(`PIE Web Component: "${e}" has already been defined. Please ensure the component is only being defined once in your application.`) : customElements.define(e, t);
|
|
47
58
|
}
|
|
48
59
|
export {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
60
|
+
a as FormControlMixin,
|
|
61
|
+
l as RtlMixin,
|
|
62
|
+
h as defineCustomElement,
|
|
63
|
+
m as requiredProperty,
|
|
64
|
+
f as validPropertyValues
|
|
53
65
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@justeattakeaway/pie-webc-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "PIE design system base classes, mixins and utilities for web components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -12,11 +12,16 @@
|
|
|
12
12
|
"lint:scripts:fix": "run -T eslint . --fix",
|
|
13
13
|
"test": "run -T vitest run",
|
|
14
14
|
"test:ci": "yarn test",
|
|
15
|
+
"test:browsers": "npx playwright test -c ./playwright-lit.config.ts",
|
|
16
|
+
"test:browsers:ci": "yarn test:browsers",
|
|
15
17
|
"test:watch": "run -T vitest"
|
|
16
18
|
},
|
|
17
19
|
"dependencies": {
|
|
18
20
|
"lit": "3.1.0"
|
|
19
21
|
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@justeattakeaway/pie-components-config": "0.7.0"
|
|
24
|
+
},
|
|
20
25
|
"volta": {
|
|
21
26
|
"extends": "../../../package.json"
|
|
22
27
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<link rel="preload" href="https://d30v2pzvrfyzpo.cloudfront.net/fonts/JETSansDigital-Regular-optimised.woff2" as="font" type="font/woff2" crossorigin>
|
|
7
|
+
<link rel="preload" href="https://d30v2pzvrfyzpo.cloudfront.net/fonts/JETSansDigital-Bold-optimised.woff2" as="font" type="font/woff2" crossorigin>
|
|
8
|
+
<link rel="preload" href="https://d30v2pzvrfyzpo.cloudfront.net/fonts/JETSansDigital-ExtraBold-optimised.woff2" as="font" type="font/woff2" crossorigin>
|
|
9
|
+
<style>
|
|
10
|
+
@font-face {
|
|
11
|
+
font-family: JETSansDigital;
|
|
12
|
+
src: url('https://d30v2pzvrfyzpo.cloudfront.net/fonts/JETSansDigital-Regular-optimised.woff2') format("woff2"),
|
|
13
|
+
url('https://d30v2pzvrfyzpo.cloudfront.net/fonts/JETSansDigital-Regular-optimised.woff') format("woff");
|
|
14
|
+
font-weight: 400;
|
|
15
|
+
font-display: swap;
|
|
16
|
+
}
|
|
17
|
+
@font-face {
|
|
18
|
+
font-family: JETSansDigital;
|
|
19
|
+
src: url('https://d30v2pzvrfyzpo.cloudfront.net/fonts/JETSansDigital-Bold-optimised.woff2') format("woff2"),
|
|
20
|
+
url('https://d30v2pzvrfyzpo.cloudfront.net/fonts/JETSansDigital-Bold-optimised.woff') format("woff");
|
|
21
|
+
font-weight: 700;
|
|
22
|
+
font-display: swap;
|
|
23
|
+
}
|
|
24
|
+
@font-face {
|
|
25
|
+
font-family: JETSansDigital;
|
|
26
|
+
src: url('https://d30v2pzvrfyzpo.cloudfront.net/fonts/JETSansDigital-ExtraBold-optimised.woff2') format("woff2"),
|
|
27
|
+
url('https://d30v2pzvrfyzpo.cloudfront.net/fonts/JETSansDigital-ExtraBold-optimised.woff') format("woff");
|
|
28
|
+
font-weight: 800;
|
|
29
|
+
font-display: swap;
|
|
30
|
+
}
|
|
31
|
+
body {
|
|
32
|
+
font-feature-settings: "tnum"; /* Enable tabular numbers */
|
|
33
|
+
}
|
|
34
|
+
/* basic styles to center align components and give them some spacing */
|
|
35
|
+
#root {
|
|
36
|
+
padding: 1em;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
#root > * {
|
|
40
|
+
display: block;
|
|
41
|
+
margin-inline: auto;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#root > * + * {
|
|
45
|
+
margin-top: 1em;
|
|
46
|
+
}
|
|
47
|
+
</style>
|
|
48
|
+
<title>Testing Page</title>
|
|
49
|
+
<link rel="stylesheet" type="text/css" href="https://unpkg.com/@justeat/pie-design-tokens/dist/jet.css" />
|
|
50
|
+
<link rel="stylesheet" type="text/css" href="https://unpkg.com/@justeat/pie-design-tokens/dist/jet-hsl-colors.css" />
|
|
51
|
+
</head>
|
|
52
|
+
<body>
|
|
53
|
+
<div id="root"></div>
|
|
54
|
+
<script type="module" src="./index.ts"></script>
|
|
55
|
+
</body>
|
|
56
|
+
</html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Import common styles here
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineConfig, devices } from '@sand4rt/experimental-ct-web';
|
|
2
|
+
import { getPlaywrightConfig as getPlaywrightConfigOG } from '@justeattakeaway/pie-components-config';
|
|
3
|
+
import type { PlaywrightTestConfig } from '@playwright/test';
|
|
4
|
+
|
|
5
|
+
const getPlaywrightConfig = () : PlaywrightTestConfig => ({
|
|
6
|
+
...getPlaywrightConfigOG(),
|
|
7
|
+
projects: [
|
|
8
|
+
{
|
|
9
|
+
name: 'component:chrome',
|
|
10
|
+
use: {
|
|
11
|
+
...devices['Desktop Chrome'],
|
|
12
|
+
},
|
|
13
|
+
testMatch: ['**/test/**/*.browser.spec.ts'],
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export default defineConfig(getPlaywrightConfig());
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import type { GenericConstructor } from '../types/GenericConstructor';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Interface for FormControl behavior.
|
|
6
|
+
*/
|
|
7
|
+
export interface FormControlInterface {
|
|
8
|
+
_internals: ElementInternals;
|
|
9
|
+
get form(): HTMLFormElement | null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Mixin to add form control behaviors to a LitElement.
|
|
14
|
+
* This mixin adds properties and methods to handle form-associated custom elements.
|
|
15
|
+
*
|
|
16
|
+
* @param superClass - The LitElement class to extend with form control functionality.
|
|
17
|
+
* @returns A class extending both the provided LitElement and _FormControlInterface.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* import { LitElement, html } from 'lit';
|
|
22
|
+
* import { FormControlMixin } from './path-to-FormControlMixin'; // Update the import path
|
|
23
|
+
*
|
|
24
|
+
* // Create a new component using the FormControlMixin
|
|
25
|
+
* class MyFormElement extends FormControlMixin(LitElement) {
|
|
26
|
+
* render() {
|
|
27
|
+
* return html`<div>Form-associated element with form: ${this.form ? 'attached' : 'detached'}</div>`;
|
|
28
|
+
* }
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* customElements.define('my-form-element', MyFormElement);
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export const FormControlMixin =
|
|
35
|
+
<T extends GenericConstructor<LitElement>>(superClass: T) => {
|
|
36
|
+
/**
|
|
37
|
+
* Class representing a LitElement that behaves like a native HTML form control element.
|
|
38
|
+
* @extends {LitElement}
|
|
39
|
+
* @implements {_FormControlInterface}
|
|
40
|
+
*/
|
|
41
|
+
class FormControlElement extends superClass implements FormControlInterface {
|
|
42
|
+
static formAssociated = true;
|
|
43
|
+
|
|
44
|
+
_internals: ElementInternals;
|
|
45
|
+
|
|
46
|
+
get form () {
|
|
47
|
+
return this._internals.form;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
51
|
+
constructor (...args: any[]) {
|
|
52
|
+
super(...args);
|
|
53
|
+
this._internals = this.attachInternals();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return FormControlElement as GenericConstructor<FormControlInterface> & T;
|
|
58
|
+
};
|
package/src/mixins/index.ts
CHANGED
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
/* eslint-disable max-classes-per-file */
|
|
2
2
|
import { LitElement, isServer } from 'lit';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* A type representing a constructor of any class.
|
|
6
|
-
* @typedef {new (...args: any[]) => T} Constructor
|
|
7
|
-
* @template T
|
|
8
|
-
*/
|
|
9
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
|
-
type Constructor<T> = new (...args: any[]) => T;
|
|
3
|
+
import type { GenericConstructor } from '../types/GenericConstructor';
|
|
11
4
|
|
|
12
5
|
/**
|
|
13
6
|
* An interface representing the structure of RTL related class.
|
|
@@ -24,8 +17,8 @@ declare class _RTLInterface {
|
|
|
24
17
|
* allowing you to easily determine the text direction within your component.
|
|
25
18
|
*
|
|
26
19
|
* @function
|
|
27
|
-
* @param {
|
|
28
|
-
* @returns {
|
|
20
|
+
* @param {GenericConstructor<LitElement>} superClass - The LitElement class to extend with RTL functionality.
|
|
21
|
+
* @returns {GenericConstructor<_RTLInterface> & T} - A new class extending both LitElement and _RTLInterface.
|
|
29
22
|
*
|
|
30
23
|
* @example
|
|
31
24
|
* ```typescript
|
|
@@ -64,7 +57,7 @@ declare class _RTLInterface {
|
|
|
64
57
|
* ```
|
|
65
58
|
*/
|
|
66
59
|
export const RtlMixin =
|
|
67
|
-
<T extends
|
|
60
|
+
<T extends GenericConstructor<LitElement>>(superClass: T) => {
|
|
68
61
|
/**
|
|
69
62
|
* Class representing a LitElement with RTL handling.
|
|
70
63
|
* @extends {LitElement}
|
|
@@ -94,5 +87,5 @@ export const RtlMixin =
|
|
|
94
87
|
}
|
|
95
88
|
}
|
|
96
89
|
|
|
97
|
-
return RTLElement as
|
|
90
|
+
return RTLElement as GenericConstructor<_RTLInterface> & T;
|
|
98
91
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import type { GenericConstructor } from './GenericConstructor';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A type representing a mixin that is compatible with classes that extend LitElement.
|
|
6
|
+
*/
|
|
7
|
+
export type LitElementMixin<T extends GenericConstructor<LitElement>> = (base: T) => T;
|
|
@@ -3,7 +3,7 @@ import { LitElement } from 'lit';
|
|
|
3
3
|
import {
|
|
4
4
|
vi, expect, it,
|
|
5
5
|
} from 'vitest';
|
|
6
|
-
import { defineCustomElement } from '
|
|
6
|
+
import { defineCustomElement } from '../../functions/defineCustomElement';
|
|
7
7
|
|
|
8
8
|
it('should call console.warn when a component is defined twice', () => {
|
|
9
9
|
// Arrange
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { LitElement, html } from 'lit';
|
|
2
|
+
import { FormControlMixin } from '../../../mixins/formControl/formControlMixin.ts';
|
|
3
|
+
import { defineCustomElement } from '../../../functions/defineCustomElement.ts';
|
|
4
|
+
|
|
5
|
+
const componentSelector = 'form-control-mixin-mock';
|
|
6
|
+
|
|
7
|
+
export class MockComponent extends FormControlMixin(LitElement) {
|
|
8
|
+
render () {
|
|
9
|
+
return html`<div>Form Control Component</div>`;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
declare global {
|
|
14
|
+
interface HTMLElementTagNameMap {
|
|
15
|
+
[componentSelector]: MockComponent;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
defineCustomElement(componentSelector, MockComponent);
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { test, expect } from '@sand4rt/experimental-ct-web';
|
|
2
|
+
import { MockComponent } from './MockComponent.ts';
|
|
3
|
+
|
|
4
|
+
test.describe('FormControlMixin', () => {
|
|
5
|
+
// IMPORTANT: Mounting and Unmounting the component before each test ensures that any tests that do not explicitly
|
|
6
|
+
// mount the component will still have it available in Playwright's cache (loaded and registered in the test browser)
|
|
7
|
+
test.beforeEach(async ({ mount }) => {
|
|
8
|
+
const component = await mount(MockComponent);
|
|
9
|
+
await component.unmount();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test.describe('form property', () => {
|
|
13
|
+
test.describe('when no form exists', () => {
|
|
14
|
+
test('should not have an associated form', async ({ page, mount }) => {
|
|
15
|
+
// Arrange
|
|
16
|
+
await mount(MockComponent);
|
|
17
|
+
|
|
18
|
+
const isFormAssociated = await page.evaluate(() => {
|
|
19
|
+
const component = document.querySelector('form-control-mixin-mock');
|
|
20
|
+
const form = component?.form;
|
|
21
|
+
|
|
22
|
+
return !!form;
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Assert
|
|
26
|
+
expect(isFormAssociated).toBe(false);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test.describe('when inside of a form', () => {
|
|
31
|
+
test('should return the associated form', async ({ page }) => {
|
|
32
|
+
// Arrange
|
|
33
|
+
await page.setContent(`
|
|
34
|
+
<form id="testForm" action="/foo" method="POST">
|
|
35
|
+
<input type="text" id="username" name="username" required>
|
|
36
|
+
<input type="password" id="password" name="password" required>
|
|
37
|
+
<form-control-mixin-mock></form-control-mixin-mock>
|
|
38
|
+
</form>
|
|
39
|
+
`);
|
|
40
|
+
|
|
41
|
+
const formId = await page.evaluate(() => {
|
|
42
|
+
const component = document.querySelector('form-control-mixin-mock');
|
|
43
|
+
const form = component?.form;
|
|
44
|
+
|
|
45
|
+
return form?.id;
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Assert
|
|
49
|
+
expect(formId).toContain('testForm');
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test.describe('when not inside of an existing form', () => {
|
|
54
|
+
test('should not have an associated form', async ({ page }) => {
|
|
55
|
+
// Arrange
|
|
56
|
+
await page.setContent(`
|
|
57
|
+
<form id="siblingForm" action="/foo" method="POST">
|
|
58
|
+
<input type="text" id="username" name="username" required>
|
|
59
|
+
<input type="password" id="password" name="password" required>
|
|
60
|
+
</form>
|
|
61
|
+
<form-control-mixin-mock></form-control-mixin-mock>
|
|
62
|
+
`);
|
|
63
|
+
|
|
64
|
+
const isFormAssociated = await page.evaluate(() => {
|
|
65
|
+
const component = document.querySelector('form-control-mixin-mock');
|
|
66
|
+
const form = component?.form;
|
|
67
|
+
|
|
68
|
+
return !!form;
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Assert
|
|
72
|
+
expect(isFormAssociated).toBe(false);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
});
|
package/tsconfig.json
CHANGED
|
@@ -1,30 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
+
"extends": "../../../configs/pie-components-config/tsconfig.json",
|
|
2
3
|
"compilerOptions": {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
"lib": ["es2020", "DOM", "DOM.Iterable"],
|
|
6
|
-
"declaration": true,
|
|
7
|
-
"declarationMap": true,
|
|
8
|
-
"sourceMap": true,
|
|
9
|
-
"inlineSources": true,
|
|
10
|
-
"outDir": "./compiled",
|
|
11
|
-
"baseUrl": ".",
|
|
12
|
-
"paths": {
|
|
13
|
-
"@/*": ["./src/*"]
|
|
14
|
-
},
|
|
15
|
-
"rootDir": ".",
|
|
16
|
-
"strict": true,
|
|
17
|
-
"noUnusedLocals": true,
|
|
18
|
-
"noUnusedParameters": true,
|
|
19
|
-
"noImplicitReturns": true,
|
|
20
|
-
"noFallthroughCasesInSwitch": true,
|
|
21
|
-
"noImplicitAny": true,
|
|
22
|
-
"noImplicitThis": true,
|
|
23
|
-
"moduleResolution": "node",
|
|
24
|
-
"allowSyntheticDefaultImports": true,
|
|
25
|
-
"experimentalDecorators": true,
|
|
26
|
-
"forceConsistentCasingInFileNames": true
|
|
4
|
+
"baseUrl": ".",
|
|
5
|
+
"rootDir": ".",
|
|
27
6
|
},
|
|
28
|
-
"include": ["src/**/*.ts","./declaration.d.ts", "test/**/*.ts", "index.ts"],
|
|
29
|
-
"exclude": []
|
|
7
|
+
"include": ["src/**/*.ts", "./declaration.d.ts", "test/**/*.ts", "index.ts", "playwright-lit.config.ts"],
|
|
30
8
|
}
|