@oslokommune/punkt-elements 13.5.0 → 13.5.1
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/CHANGELOG.md +17 -0
- package/dist/{card-Dtw26f7i.js → card-BDz4RWxK.js} +1 -1
- package/dist/{card-BUITGoqX.cjs → card-DBlFf1ry.cjs} +1 -1
- package/dist/{heading-D6jXE_Mz.js → heading-Bdh9absf.js} +22 -22
- package/dist/heading-CNycsyMj.cjs +1 -0
- package/dist/pkt-card.cjs +1 -1
- package/dist/pkt-card.js +1 -1
- package/dist/pkt-heading.cjs +1 -1
- package/dist/pkt-heading.js +1 -1
- package/dist/pkt-index.cjs +1 -1
- package/dist/pkt-index.js +2 -2
- package/package.json +2 -2
- package/src/components/consent/consent.test.ts +436 -0
- package/src/components/heading/heading.test.ts +458 -0
- package/src/components/heading/heading.ts +3 -0
- package/src/components/helptext/helptext.test.ts +474 -0
- package/dist/heading-BRE_iFtR.cjs +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,23 @@ og skriver commits ca etter [Conventional Commits](https://conventionalcommits.o
|
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
+
## [13.5.1](https://github.com/oslokommune/punkt/compare/13.5.0...13.5.1) (2025-09-08)
|
|
9
|
+
|
|
10
|
+
### ⚠ BREAKING CHANGES
|
|
11
|
+
Ingen
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
Ingen
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
Ingen
|
|
18
|
+
|
|
19
|
+
### Chores
|
|
20
|
+
Ingen
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
|
|
8
25
|
## [13.5.0](https://github.com/oslokommune/punkt/compare/13.4.2...13.5.0) (2025-09-05)
|
|
9
26
|
|
|
10
27
|
### ⚠ BREAKING CHANGES
|
|
@@ -5,7 +5,7 @@ import { P as $ } from "./pkt-slot-controller-BPGj-LC5.js";
|
|
|
5
5
|
import { e as y, n as _ } from "./ref-BBYSqgeW.js";
|
|
6
6
|
import "./icon-CC1js8eR.js";
|
|
7
7
|
import "./tag-DyXzTY68.js";
|
|
8
|
-
import "./heading-
|
|
8
|
+
import "./heading-Bdh9absf.js";
|
|
9
9
|
const b = {
|
|
10
10
|
layout: {
|
|
11
11
|
default: "vertical"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";const p=require("./class-map-BBG2gMX4.cjs"),h=require("./if-defined-Cni-RHLS.cjs"),t=require("./element-6DBpyGQm.cjs"),g=require("./pkt-slot-controller-BzddBp7z.cjs"),c=require("./ref-iJtiv3o2.cjs");require("./icon-B_ryAy4Q.cjs");require("./tag-Bbs0U_Au.cjs");require("./heading-
|
|
1
|
+
"use strict";const p=require("./class-map-BBG2gMX4.cjs"),h=require("./if-defined-Cni-RHLS.cjs"),t=require("./element-6DBpyGQm.cjs"),g=require("./pkt-slot-controller-BzddBp7z.cjs"),c=require("./ref-iJtiv3o2.cjs");require("./icon-B_ryAy4Q.cjs");require("./tag-Bbs0U_Au.cjs");require("./heading-CNycsyMj.cjs");const k={layout:{default:"vertical"},skin:{type:["outlined","outlined-beige","gray","blue","beige","green"],default:"outlined"},padding:{default:"default"}},o={props:k};var u=Object.defineProperty,m=Object.getOwnPropertyDescriptor,e=(i,a,s,n)=>{for(var r=n>1?void 0:n?m(a,s):a,d=i.length-1,l;d>=0;d--)(l=i[d])&&(r=(n?l(a,s,r):l(r))||r);return n&&r&&u(a,s,r),r};exports.PktCard=class extends t.PktElement{constructor(){super(),this.defaultSlot=c.e(),this.ariaLabel="",this.metaLead=null,this.borderOnHover=!0,this.clickCardLink=null,this.metaTrail=null,this.layout=o.props.layout.default,this.heading="",this.headinglevel=3,this.image={src:"",alt:""},this.imageShape="square",this.openLinkInNewTab=!1,this.padding=o.props.padding.default,this.skin=o.props.skin.default,this.subheading="",this.tagPosition="top",this.tags=[],this.slotController=new g.PktSlotController(this,this.defaultSlot)}connectedCallback(){super.connectedCallback()}render(){var r,d;const a={"pkt-card":!0,[`pkt-card--${this.skin}`]:this.skin,[`pkt-card--${this.layout}`]:this.layout,[`pkt-card--padding-${this.padding}`]:this.padding,"pkt-card--border-on-hover":this.borderOnHover},s=((r=this.ariaLabel)==null?void 0:r.trim())||(this.heading?`${this.heading} lenkekort`:"lenkekort"),n=((d=this.ariaLabel)==null?void 0:d.trim())||(this.heading?this.heading:"kort");return t.x`
|
|
2
2
|
<article
|
|
3
3
|
class=${p.e(a)}
|
|
4
4
|
aria-label=${h.o(this.clickCardLink?s:n)}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { b as p, x as u, n
|
|
2
|
-
var g = Object.defineProperty,
|
|
3
|
-
for (var s =
|
|
4
|
-
(h = t[
|
|
5
|
-
return
|
|
1
|
+
import { b as p, x as u, n, a as o } from "./element-CgEWt74-.js";
|
|
2
|
+
var g = Object.defineProperty, f = Object.getOwnPropertyDescriptor, a = (t, i, e, d) => {
|
|
3
|
+
for (var s = d > 1 ? void 0 : d ? f(i, e) : i, r = t.length - 1, h; r >= 0; r--)
|
|
4
|
+
(h = t[r]) && (s = (d ? h(i, e, s) : h(s)) || s);
|
|
5
|
+
return d && s && g(i, e, s), s;
|
|
6
6
|
};
|
|
7
|
-
let
|
|
7
|
+
let l = class extends p {
|
|
8
8
|
constructor() {
|
|
9
9
|
super(...arguments), this.size = "medium", this.level = 2, this.visuallyHidden = !1, this.align = "start";
|
|
10
10
|
}
|
|
@@ -12,7 +12,7 @@ let a = class extends p {
|
|
|
12
12
|
super.connectedCallback(), this.setAttribute("role", "heading"), this.setAttribute("aria-level", String(this.level)), this.updateHostClasses();
|
|
13
13
|
}
|
|
14
14
|
attributeChangedCallback(t, i, e) {
|
|
15
|
-
super.attributeChangedCallback(t, i, e), t === "level" && e && this.setLevel(Number(e)), (t === "size" || t === "visuallyHidden" || t === "align") && this.updateHostClasses();
|
|
15
|
+
super.attributeChangedCallback(t, i, e), t === "level" && e && this.setLevel(Number(e)), t === "visuallyHidden" && (this.visuallyHidden = e !== null && e !== "false"), (t === "size" || t === "visuallyHidden" || t === "align") && this.updateHostClasses();
|
|
16
16
|
}
|
|
17
17
|
updated(t) {
|
|
18
18
|
super.updated(t), t.has("level") && this.setLevel(this.level), (t.has("size") || t.has("visuallyHidden") || t.has("align")) && this.updateHostClasses();
|
|
@@ -38,21 +38,21 @@ let a = class extends p {
|
|
|
38
38
|
return u`<slot></slot>`;
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
],
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
],
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
],
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
],
|
|
53
|
-
|
|
41
|
+
a([
|
|
42
|
+
n({ type: String, reflect: !0 })
|
|
43
|
+
], l.prototype, "size", 2);
|
|
44
|
+
a([
|
|
45
|
+
n({ type: Number, reflect: !0 })
|
|
46
|
+
], l.prototype, "level", 2);
|
|
47
|
+
a([
|
|
48
|
+
n({ type: Boolean, reflect: !0 })
|
|
49
|
+
], l.prototype, "visuallyHidden", 2);
|
|
50
|
+
a([
|
|
51
|
+
n({ type: String, reflect: !0 })
|
|
52
|
+
], l.prototype, "align", 2);
|
|
53
|
+
l = a([
|
|
54
54
|
o("pkt-heading")
|
|
55
|
-
],
|
|
55
|
+
], l);
|
|
56
56
|
export {
|
|
57
|
-
|
|
57
|
+
l as P
|
|
58
58
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";const i=require("./element-6DBpyGQm.cjs");var h=Object.defineProperty,p=Object.getOwnPropertyDescriptor,l=(n,t,a,e)=>{for(var s=e>1?void 0:e?p(t,a):t,d=n.length-1,r;d>=0;d--)(r=n[d])&&(s=(e?r(t,a,s):r(s))||s);return e&&s&&h(t,a,s),s};exports.PktHeading=class extends i.PktShadowElement{constructor(){super(...arguments),this.size="medium",this.level=2,this.visuallyHidden=!1,this.align="start"}connectedCallback(){super.connectedCallback(),this.setAttribute("role","heading"),this.setAttribute("aria-level",String(this.level)),this.updateHostClasses()}attributeChangedCallback(t,a,e){super.attributeChangedCallback(t,a,e),t==="level"&&e&&this.setLevel(Number(e)),t==="visuallyHidden"&&(this.visuallyHidden=e!==null&&e!=="false"),(t==="size"||t==="visuallyHidden"||t==="align")&&this.updateHostClasses()}updated(t){super.updated(t),t.has("level")&&this.setLevel(this.level),(t.has("size")||t.has("visuallyHidden")||t.has("align"))&&this.updateHostClasses()}setLevel(t){t>=1&&t<=6?(this.level=t,this.setAttribute("aria-level",String(t))):console.warn(`Invalid heading level: ${t}. Must be between 1 and 6.`)}updateHostClasses(){this.classList.remove("pkt-heading","pkt-heading--xsmall","pkt-heading--small","pkt-heading--medium","pkt-heading--large","pkt-heading--xlarge","pkt-sr-only","pkt-heading--start","pkt-heading--center","pkt-heading--end"),this.classList.add("pkt-heading"),this.size&&this.classList.add(`pkt-heading--${this.size}`),this.visuallyHidden&&this.classList.add("pkt-sr-only"),this.align&&this.classList.add(`pkt-heading--${this.align}`)}render(){return i.x`<slot></slot>`}};l([i.n({type:String,reflect:!0})],exports.PktHeading.prototype,"size",2);l([i.n({type:Number,reflect:!0})],exports.PktHeading.prototype,"level",2);l([i.n({type:Boolean,reflect:!0})],exports.PktHeading.prototype,"visuallyHidden",2);l([i.n({type:String,reflect:!0})],exports.PktHeading.prototype,"align",2);exports.PktHeading=l([i.t("pkt-heading")],exports.PktHeading);
|
package/dist/pkt-card.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./card-
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./card-DBlFf1ry.cjs"),t=e.PktCard;Object.defineProperty(exports,"PktCard",{enumerable:!0,get:()=>e.PktCard});exports.default=t;
|
package/dist/pkt-card.js
CHANGED
package/dist/pkt-heading.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./heading-
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./heading-CNycsyMj.cjs"),t=e.PktHeading;Object.defineProperty(exports,"PktHeading",{enumerable:!0,get:()=>e.PktHeading});exports.default=t;
|
package/dist/pkt-heading.js
CHANGED
package/dist/pkt-index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const P=require("./alert-DQNBDKjT.cjs"),l=require("./accordionitem-Csh7iSVG.cjs"),d=require("./backlink-JbBNi3qg.cjs"),b=require("./button-B8rdtaHB.cjs"),k=require("./calendar-32W9p9uc.cjs"),m=require("./card-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const P=require("./alert-DQNBDKjT.cjs"),l=require("./accordionitem-Csh7iSVG.cjs"),d=require("./backlink-JbBNi3qg.cjs"),b=require("./button-B8rdtaHB.cjs"),k=require("./calendar-32W9p9uc.cjs"),m=require("./card-DBlFf1ry.cjs"),g=require("./combobox-DjO0RMUB.cjs"),h=require("./consent-hYeFWNFr.cjs"),f=require("./checkbox-Gn7Wtk9h.cjs"),t=require("./element-6DBpyGQm.cjs"),y=require("./pkt-slot-controller-BzddBp7z.cjs"),s=require("./ref-iJtiv3o2.cjs"),O=require("./class-map-BBG2gMX4.cjs"),j=require("./datepicker-CmTrG5GE.cjs"),q=require("./helptext-CzQX6YVE.cjs"),x=require("./heading-CNycsyMj.cjs"),C=require("./icon-B_ryAy4Q.cjs"),v=require("./input-wrapper-CZ-a00V7.cjs"),S=require("./link-Cjl0xwSq.cjs"),$=require("./linkcard-BlMhPNry.cjs"),L=require("./loader-CHPxY9c6.cjs"),_=require("./messagebox-CqUBJs_D.cjs"),A=require("./modal-CRtxhCaP.cjs"),B=require("./progressbar-DhMBXkww.cjs"),p=require("./radiobutton-CdT6v1oq.cjs"),T=require("./tag-Bbs0U_Au.cjs"),I=require("./textarea-CPXsMFUq.cjs"),M=require("./textinput-aNI5kibM.cjs"),R=require("./select-Dkl0KhGW.cjs");var H=Object.defineProperty,w=Object.getOwnPropertyDescriptor,o=(a,e,r,i)=>{for(var n=i>1?void 0:i?w(e,r):e,u=a.length-1,c;u>=0;u--)(c=a[u])&&(n=(i?c(e,r,n):c(n))||n);return i&&n&&H(e,r,n),n};exports.PktComponent=class extends t.PktElement{constructor(){super(),this.string="",this.strings=[],this.darkmode=!1,this._list=[],this.defaultSlot=s.e(),this.namedSlot=s.e(),this.slotController=new y.PktSlotController(this,this.defaultSlot,this.namedSlot)}connectedCallback(){this.strings.length&&this.strings.forEach(e=>{this._list.push(e.toUpperCase())}),super.connectedCallback()}render(){const e={"pkt-component":!0,"pkt-component--has-list":this.strings.length>0,"pkt-darkmode":this.darkmode};return t.x`
|
|
2
2
|
<div class="${O.e(e)}">
|
|
3
3
|
<h1 class="pkt-txt-28">${this.string}</h1>
|
|
4
4
|
|
package/dist/pkt-index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { P as O } from "./backlink-C2jbzu0U.js";
|
|
|
4
4
|
import { P as T } from "./button-DhispFOY.js";
|
|
5
5
|
import { c as f } from "./calendar-CJSxvwAq.js";
|
|
6
6
|
import { P as D } from "./calendar-CJSxvwAq.js";
|
|
7
|
-
import { P as G } from "./card-
|
|
7
|
+
import { P as G } from "./card-BDz4RWxK.js";
|
|
8
8
|
import { P as K } from "./combobox-yE4aYhTi.js";
|
|
9
9
|
import { P as U } from "./consent-BpcQFvbi.js";
|
|
10
10
|
import { P as q } from "./checkbox-ym7z6cpt.js";
|
|
@@ -14,7 +14,7 @@ import { e as m, n as d } from "./ref-BBYSqgeW.js";
|
|
|
14
14
|
import { e as u } from "./class-map-BpTj9gtz.js";
|
|
15
15
|
import { P as F } from "./datepicker-BJKJBoy_.js";
|
|
16
16
|
import { P as Q } from "./helptext-B7eI0iBQ.js";
|
|
17
|
-
import { P as X } from "./heading-
|
|
17
|
+
import { P as X } from "./heading-Bdh9absf.js";
|
|
18
18
|
import { P as Z } from "./icon-CC1js8eR.js";
|
|
19
19
|
import { P as et } from "./input-wrapper-Dr__Sxql.js";
|
|
20
20
|
import { P as ot } from "./link-AIyVfcyH.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oslokommune/punkt-elements",
|
|
3
|
-
"version": "13.5.
|
|
3
|
+
"version": "13.5.1",
|
|
4
4
|
"description": "Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo",
|
|
5
5
|
"homepage": "https://punkt.oslo.kommune.no",
|
|
6
6
|
"author": "Team Designsystem, Oslo Origo",
|
|
@@ -69,5 +69,5 @@
|
|
|
69
69
|
"url": "https://github.com/oslokommune/punkt/issues"
|
|
70
70
|
},
|
|
71
71
|
"license": "MIT",
|
|
72
|
-
"gitHead": "
|
|
72
|
+
"gitHead": "5892d94f903527e3e228915d86653bfbfdf209c8"
|
|
73
73
|
}
|
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
import '@testing-library/jest-dom'
|
|
2
|
+
import { axe, toHaveNoViolations } from 'jest-axe'
|
|
3
|
+
import { fireEvent } from '@testing-library/dom'
|
|
4
|
+
|
|
5
|
+
expect.extend(toHaveNoViolations)
|
|
6
|
+
|
|
7
|
+
import './consent'
|
|
8
|
+
import { PktConsent } from './consent'
|
|
9
|
+
|
|
10
|
+
const waitForCustomElements = async () => {
|
|
11
|
+
await customElements.whenDefined('pkt-consent')
|
|
12
|
+
await customElements.whenDefined('pkt-button')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Helper function to create consent markup
|
|
16
|
+
const createConsent = async (consentProps = '') => {
|
|
17
|
+
const container = document.createElement('div')
|
|
18
|
+
container.innerHTML = `
|
|
19
|
+
<pkt-consent ${consentProps}></pkt-consent>
|
|
20
|
+
`
|
|
21
|
+
document.body.appendChild(container)
|
|
22
|
+
await waitForCustomElements()
|
|
23
|
+
return container
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Cleanup after each test
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
document.body.innerHTML = ''
|
|
29
|
+
// Clean up any injected scripts
|
|
30
|
+
const existingScript = document.querySelector('#oslo-consent-script')
|
|
31
|
+
if (existingScript) {
|
|
32
|
+
existingScript.remove()
|
|
33
|
+
}
|
|
34
|
+
const existingStyles = document.querySelector('#oslo-consent-styles')
|
|
35
|
+
if (existingStyles) {
|
|
36
|
+
existingStyles.remove()
|
|
37
|
+
}
|
|
38
|
+
// Clean up global variables
|
|
39
|
+
delete window.cookieBanner_googleAnalyticsId
|
|
40
|
+
delete window.cookieBanner_hotjarId
|
|
41
|
+
delete window.cookieBanner_devMode
|
|
42
|
+
delete window.cookieBanner_cookieDomain
|
|
43
|
+
delete window.cookieBanner_cookieSecure
|
|
44
|
+
delete window.cookieBanner_cookieExpiryDays
|
|
45
|
+
delete window.cookieBanner
|
|
46
|
+
delete window.__cookieEvents
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
describe('PktConsent', () => {
|
|
50
|
+
describe('Rendering and basic functionality', () => {
|
|
51
|
+
test('renders without errors', async () => {
|
|
52
|
+
const container = await createConsent()
|
|
53
|
+
|
|
54
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
55
|
+
expect(consent).toBeInTheDocument()
|
|
56
|
+
|
|
57
|
+
await consent.updateComplete
|
|
58
|
+
expect(consent).toBeTruthy()
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
test('renders with default trigger type as button', async () => {
|
|
62
|
+
const container = await createConsent()
|
|
63
|
+
|
|
64
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
65
|
+
await consent.updateComplete
|
|
66
|
+
|
|
67
|
+
expect(consent.triggerType).toBe('button')
|
|
68
|
+
|
|
69
|
+
const button = consent.querySelector('pkt-button')
|
|
70
|
+
expect(button).toBeInTheDocument()
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test('renders with custom trigger text', async () => {
|
|
74
|
+
const customText = 'Custom consent settings'
|
|
75
|
+
const container = await createConsent(`triggerText="${customText}"`)
|
|
76
|
+
|
|
77
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
78
|
+
await consent.updateComplete
|
|
79
|
+
|
|
80
|
+
expect(consent.triggerText).toBe(customText)
|
|
81
|
+
const button = consent.querySelector('pkt-button')
|
|
82
|
+
expect(button?.textContent?.trim()).toBe(customText)
|
|
83
|
+
})
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
describe('Properties and attributes', () => {
|
|
87
|
+
test('applies default properties correctly', async () => {
|
|
88
|
+
const container = await createConsent()
|
|
89
|
+
|
|
90
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
91
|
+
await consent.updateComplete
|
|
92
|
+
|
|
93
|
+
expect(consent.devMode).toBe(false)
|
|
94
|
+
expect(consent.triggerType).toBe('button')
|
|
95
|
+
expect(consent.i18nLanguage).toBe('nb')
|
|
96
|
+
expect(consent.hotjarId).toBe(null)
|
|
97
|
+
expect(consent.googleAnalyticsId).toBe(null)
|
|
98
|
+
expect(consent.cookieDomain).toBe(null)
|
|
99
|
+
expect(consent.cookieSecure).toBe(null)
|
|
100
|
+
expect(consent.cookieExpiryDays).toBe(null)
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
test('sets dev mode correctly', async () => {
|
|
104
|
+
const container = await createConsent('devMode')
|
|
105
|
+
|
|
106
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
107
|
+
await consent.updateComplete
|
|
108
|
+
|
|
109
|
+
expect(consent.devMode).toBe(true)
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
test('sets analytics IDs correctly', async () => {
|
|
113
|
+
const googleId = 'GA-123456789'
|
|
114
|
+
const hotjarId = 'HJ-987654321'
|
|
115
|
+
const container = await createConsent(
|
|
116
|
+
`googleAnalyticsId="${googleId}" hotjarId="${hotjarId}"`,
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
120
|
+
await consent.updateComplete
|
|
121
|
+
|
|
122
|
+
expect(consent.googleAnalyticsId).toBe(googleId)
|
|
123
|
+
expect(consent.hotjarId).toBe(hotjarId)
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
test('sets cookie configuration correctly', async () => {
|
|
127
|
+
const domain = '.example.com'
|
|
128
|
+
const secure = 'true'
|
|
129
|
+
const expiryDays = '365'
|
|
130
|
+
const container = await createConsent(
|
|
131
|
+
`cookieDomain="${domain}" cookieSecure="${secure}" cookieExpiryDays="${expiryDays}"`,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
135
|
+
await consent.updateComplete
|
|
136
|
+
|
|
137
|
+
expect(consent.cookieDomain).toBe(domain)
|
|
138
|
+
expect(consent.cookieSecure).toBe(secure)
|
|
139
|
+
expect(consent.cookieExpiryDays).toBe(expiryDays)
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
test('sets language correctly', async () => {
|
|
143
|
+
const container = await createConsent('i18nLanguage="en"')
|
|
144
|
+
|
|
145
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
146
|
+
await consent.updateComplete
|
|
147
|
+
|
|
148
|
+
expect(consent.i18nLanguage).toBe('en')
|
|
149
|
+
})
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
describe('Trigger types', () => {
|
|
153
|
+
test('renders as button trigger type', async () => {
|
|
154
|
+
const container = await createConsent('triggerType="button"')
|
|
155
|
+
|
|
156
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
157
|
+
await consent.updateComplete
|
|
158
|
+
|
|
159
|
+
expect(consent.triggerType).toBe('button')
|
|
160
|
+
const button = consent.querySelector('pkt-button')
|
|
161
|
+
expect(button).toBeInTheDocument()
|
|
162
|
+
expect(button?.getAttribute('skin')).toBe(null) // Default button
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
test('renders as link trigger type', async () => {
|
|
166
|
+
const container = await createConsent('triggerType="link"')
|
|
167
|
+
|
|
168
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
169
|
+
await consent.updateComplete
|
|
170
|
+
|
|
171
|
+
expect(consent.triggerType).toBe('link')
|
|
172
|
+
const link = consent.querySelector('a.pkt-link')
|
|
173
|
+
expect(link).toBeInTheDocument()
|
|
174
|
+
expect(link?.getAttribute('href')).toBe('#')
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
test('renders as footer link trigger type', async () => {
|
|
178
|
+
const container = await createConsent('triggerType="footerlink"')
|
|
179
|
+
|
|
180
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
181
|
+
await consent.updateComplete
|
|
182
|
+
|
|
183
|
+
expect(consent.triggerType).toBe('footerlink')
|
|
184
|
+
const footerLink = consent.querySelector('a.pkt-footer__link')
|
|
185
|
+
expect(footerLink).toBeInTheDocument()
|
|
186
|
+
|
|
187
|
+
const icon = footerLink?.querySelector('pkt-icon')
|
|
188
|
+
expect(icon).toBeInTheDocument()
|
|
189
|
+
expect(icon?.getAttribute('name')).toBe('chevron-right')
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
test('renders as icon trigger type', async () => {
|
|
193
|
+
const container = await createConsent('triggerType="icon"')
|
|
194
|
+
|
|
195
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
196
|
+
await consent.updateComplete
|
|
197
|
+
|
|
198
|
+
expect(consent.triggerType).toBe('icon')
|
|
199
|
+
const button = consent.querySelector('pkt-button')
|
|
200
|
+
expect(button).toBeInTheDocument()
|
|
201
|
+
expect(button?.getAttribute('skin')).toBe('tertiary')
|
|
202
|
+
expect(button?.getAttribute('variant')).toBe('icon-only')
|
|
203
|
+
expect(button?.getAttribute('iconName')).toBe('cookie')
|
|
204
|
+
})
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
describe('Event handling', () => {
|
|
208
|
+
beforeEach(() => {
|
|
209
|
+
// Mock the entire window.cookieBanner object
|
|
210
|
+
Object.defineProperty(window, 'cookieBanner', {
|
|
211
|
+
value: {
|
|
212
|
+
cookieConsent: {
|
|
213
|
+
validateConsentCookie: jest.fn().mockResolvedValue(true),
|
|
214
|
+
getConsentCookie: jest.fn().mockReturnValue('mock-cookie'),
|
|
215
|
+
},
|
|
216
|
+
openCookieModal: jest.fn(),
|
|
217
|
+
},
|
|
218
|
+
writable: true,
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
// Mock window.__cookieEvents
|
|
222
|
+
Object.defineProperty(window, '__cookieEvents', {
|
|
223
|
+
value: {
|
|
224
|
+
on: jest.fn(),
|
|
225
|
+
off: jest.fn(),
|
|
226
|
+
},
|
|
227
|
+
writable: true,
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
// Use fake timers to control setTimeout
|
|
231
|
+
jest.useFakeTimers()
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
afterEach(() => {
|
|
235
|
+
// Clean up mocks and timers
|
|
236
|
+
jest.useRealTimers()
|
|
237
|
+
delete (window as any).cookieBanner
|
|
238
|
+
delete (window as any).__cookieEvents
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
test('handles click event on button trigger', async () => {
|
|
242
|
+
const container = await createConsent()
|
|
243
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
244
|
+
await consent.updateComplete
|
|
245
|
+
|
|
246
|
+
const button = consent.querySelector('pkt-button')
|
|
247
|
+
expect(button).toBeInTheDocument()
|
|
248
|
+
|
|
249
|
+
fireEvent.click(button!)
|
|
250
|
+
|
|
251
|
+
// Fast-forward time to trigger setTimeout
|
|
252
|
+
jest.runAllTimers()
|
|
253
|
+
|
|
254
|
+
expect(window.cookieBanner.openCookieModal).toHaveBeenCalled()
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
test('handles click event on link trigger', async () => {
|
|
258
|
+
const container = await createConsent('triggerType="link"')
|
|
259
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
260
|
+
await consent.updateComplete
|
|
261
|
+
|
|
262
|
+
const link = consent.querySelector('a.pkt-link')
|
|
263
|
+
expect(link).toBeInTheDocument()
|
|
264
|
+
|
|
265
|
+
fireEvent.click(link!)
|
|
266
|
+
|
|
267
|
+
// Fast-forward time to trigger setTimeout
|
|
268
|
+
jest.runAllTimers()
|
|
269
|
+
|
|
270
|
+
expect(window.cookieBanner.openCookieModal).toHaveBeenCalled()
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
test('dispatches toggle-consent event', async () => {
|
|
274
|
+
const container = await createConsent()
|
|
275
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
276
|
+
await consent.updateComplete
|
|
277
|
+
|
|
278
|
+
let eventFired = false
|
|
279
|
+
let eventDetail: any = null
|
|
280
|
+
|
|
281
|
+
consent.addEventListener('toggle-consent', (e: Event) => {
|
|
282
|
+
eventFired = true
|
|
283
|
+
eventDetail = (e as CustomEvent).detail
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
// Mock consent data
|
|
287
|
+
const mockConsent = {
|
|
288
|
+
value: JSON.stringify({
|
|
289
|
+
items: [
|
|
290
|
+
{ name: 'analytics', consent: true },
|
|
291
|
+
{ name: 'marketing', consent: false },
|
|
292
|
+
],
|
|
293
|
+
}),
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
consent.emitCookieConsents(mockConsent)
|
|
297
|
+
|
|
298
|
+
expect(eventFired).toBe(true)
|
|
299
|
+
expect(eventDetail).toEqual({
|
|
300
|
+
analytics: true,
|
|
301
|
+
marketing: false,
|
|
302
|
+
})
|
|
303
|
+
})
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
describe('Utility methods', () => {
|
|
307
|
+
test('returnJsonOrObject handles JSON strings', async () => {
|
|
308
|
+
const container = await createConsent()
|
|
309
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
310
|
+
|
|
311
|
+
const jsonString = '{"test": "value"}'
|
|
312
|
+
const result = consent.returnJsonOrObject(jsonString)
|
|
313
|
+
|
|
314
|
+
expect(result).toEqual({ test: 'value' })
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
test('returnJsonOrObject handles non-JSON objects', async () => {
|
|
318
|
+
const container = await createConsent()
|
|
319
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
320
|
+
|
|
321
|
+
const nonJsonObject = { test: 'value' }
|
|
322
|
+
const result = consent.returnJsonOrObject(nonJsonObject)
|
|
323
|
+
|
|
324
|
+
expect(result).toEqual(nonJsonObject)
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
test('returnJsonOrObject handles invalid JSON gracefully', async () => {
|
|
328
|
+
const container = await createConsent()
|
|
329
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
330
|
+
|
|
331
|
+
const invalidJson = 'invalid json string'
|
|
332
|
+
const result = consent.returnJsonOrObject(invalidJson)
|
|
333
|
+
|
|
334
|
+
expect(result).toBe(invalidJson)
|
|
335
|
+
})
|
|
336
|
+
})
|
|
337
|
+
|
|
338
|
+
describe('Accessibility', () => {
|
|
339
|
+
test('button trigger is accessible', async () => {
|
|
340
|
+
const container = await createConsent('triggerText="Cookie settings"')
|
|
341
|
+
|
|
342
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
343
|
+
await consent.updateComplete
|
|
344
|
+
|
|
345
|
+
const results = await axe(container)
|
|
346
|
+
expect(results).toHaveNoViolations()
|
|
347
|
+
|
|
348
|
+
const button = consent.querySelector('pkt-button')
|
|
349
|
+
expect(button).toBeInTheDocument()
|
|
350
|
+
expect(button?.textContent?.trim()).toBe('Cookie settings')
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
test('link trigger is accessible', async () => {
|
|
354
|
+
const container = await createConsent('triggerType="link" triggerText="Cookie settings"')
|
|
355
|
+
|
|
356
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
357
|
+
await consent.updateComplete
|
|
358
|
+
|
|
359
|
+
const results = await axe(container)
|
|
360
|
+
expect(results).toHaveNoViolations()
|
|
361
|
+
|
|
362
|
+
const link = consent.querySelector('a')
|
|
363
|
+
expect(link).toBeInTheDocument()
|
|
364
|
+
expect(link?.textContent?.trim()).toBe('Cookie settings')
|
|
365
|
+
})
|
|
366
|
+
|
|
367
|
+
test('footer link trigger is accessible', async () => {
|
|
368
|
+
const container = await createConsent(
|
|
369
|
+
'triggerType="footerlink" triggerText="Cookie settings"',
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
373
|
+
await consent.updateComplete
|
|
374
|
+
|
|
375
|
+
const results = await axe(container)
|
|
376
|
+
expect(results).toHaveNoViolations()
|
|
377
|
+
|
|
378
|
+
const link = consent.querySelector('a.pkt-footer__link')
|
|
379
|
+
expect(link).toBeInTheDocument()
|
|
380
|
+
expect(link?.textContent?.trim()).toContain('Cookie settings')
|
|
381
|
+
})
|
|
382
|
+
|
|
383
|
+
test('icon trigger is accessible', async () => {
|
|
384
|
+
const container = await createConsent('triggerType="icon" triggerText="Cookie settings"')
|
|
385
|
+
|
|
386
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
387
|
+
await consent.updateComplete
|
|
388
|
+
|
|
389
|
+
const results = await axe(container)
|
|
390
|
+
expect(results).toHaveNoViolations()
|
|
391
|
+
|
|
392
|
+
const button = consent.querySelector('pkt-button')
|
|
393
|
+
expect(button).toBeInTheDocument()
|
|
394
|
+
expect(button?.textContent?.trim()).toContain('Cookie settings')
|
|
395
|
+
})
|
|
396
|
+
})
|
|
397
|
+
|
|
398
|
+
describe('Integration and lifecycle', () => {
|
|
399
|
+
test('sets global variables on firstUpdated', async () => {
|
|
400
|
+
const googleId = 'GA-123456789'
|
|
401
|
+
const hotjarId = 'HJ-987654321'
|
|
402
|
+
const container = await createConsent(
|
|
403
|
+
`devMode googleAnalyticsId="${googleId}" hotjarId="${hotjarId}" cookieDomain=".test.com"`,
|
|
404
|
+
)
|
|
405
|
+
|
|
406
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
407
|
+
await consent.updateComplete
|
|
408
|
+
|
|
409
|
+
expect(window.cookieBanner_googleAnalyticsId).toBe(googleId)
|
|
410
|
+
expect(window.cookieBanner_hotjarId).toBe(hotjarId)
|
|
411
|
+
expect(window.cookieBanner_devMode).toBe(true)
|
|
412
|
+
expect(window.cookieBanner_cookieDomain).toBe('.test.com')
|
|
413
|
+
})
|
|
414
|
+
|
|
415
|
+
test('cleans up event listeners on disconnect', async () => {
|
|
416
|
+
const container = await createConsent()
|
|
417
|
+
const consent = container.querySelector('pkt-consent') as PktConsent
|
|
418
|
+
await consent.updateComplete
|
|
419
|
+
|
|
420
|
+
// Mock the event system
|
|
421
|
+
window.__cookieEvents = {
|
|
422
|
+
on: jest.fn(),
|
|
423
|
+
off: jest.fn(),
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// Set up a handler
|
|
427
|
+
const mockHandler = jest.fn()
|
|
428
|
+
consent['_cookieEventHandler'] = mockHandler
|
|
429
|
+
|
|
430
|
+
// Disconnect the component
|
|
431
|
+
consent.disconnectedCallback()
|
|
432
|
+
|
|
433
|
+
expect(window.__cookieEvents.off).toHaveBeenCalledWith('CookieManager.setCookie', mockHandler)
|
|
434
|
+
})
|
|
435
|
+
})
|
|
436
|
+
})
|