mkfashion-sdk 2.4.7 → 2.4.9

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/index.html CHANGED
@@ -1,79 +1,79 @@
1
- <!DOCTYPE html>
2
- <html lang="pt-BR">
3
-
4
- <head>
5
- <meta charset="UTF-8">
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>Provador Virtual</title>
8
- <script src="./src/mkfashion.js"></script>
9
- </head>
10
-
11
- <body>
12
-
13
- <div id="mkfashion-container"></div>
14
-
15
- <script>
16
- (function () {
17
- var projectid = '69f9e5b0f4eb0c4403319830';
18
- var identifier = '1881';
19
-
20
- function initMkFashion() {
21
- mkfashion.addToCart(function (payload) {
22
- console.log('Adicionando ao carrinho:', payload);
23
-
24
- var variantSku = payload.selectedIdentifier;
25
-
26
- fetch('/cart/add.js', {
27
- method: 'POST',
28
- headers: {
29
- 'Content-Type': 'application/json',
30
- },
31
- body: JSON.stringify({
32
- items: [{
33
- quantity: 1,
34
- id: variantSku
35
- }]
36
- })
37
- })
38
- .then(function (response) {
39
- return response.json();
40
- })
41
- .then(function (data) {
42
- console.log('Produto adicionado:', data);
43
- // document.dispatchEvent(new CustomEvent('cart:updated'));
44
- })
45
- .catch(function (error) {
46
- console.error('Erro carrinho:', error);
47
- });
48
- });
49
-
50
- mkfashion.onInteraction(function (data) {
51
- console.log(data.category, data.action);
52
- });
53
-
54
- mkfashion.init({
55
- projectId: projectid,
56
- identifier: identifier,
57
- target: '#mkfashion-container'
58
- });
59
- }
60
-
61
- function waitForMkFashion() {
62
- if (typeof mkfashion !== 'undefined') {
63
- initMkFashion();
64
- } else {
65
- setTimeout(waitForMkFashion, 100);
66
- }
67
- }
68
-
69
- if (document.readyState === "loading") {
70
- document.addEventListener("DOMContentLoaded", waitForMkFashion);
71
- } else {
72
- waitForMkFashion();
73
- }
74
- })();
75
- </script>
76
-
77
- </body>
78
-
79
- </html>
1
+ <!DOCTYPE html>
2
+ <html lang="pt-BR">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Provador Virtual</title>
8
+ <script src="./src/mkfashion.js"></script>
9
+ </head>
10
+
11
+ <body>
12
+
13
+ <div id="mkfashion-container"></div>
14
+
15
+ <script>
16
+ (function () {
17
+ var projectid = '69f9e5b0f4eb0c4403319830';
18
+ var identifier = '1881';
19
+
20
+ function initMkFashion() {
21
+ mkfashion.addToCart(function (payload) {
22
+ console.log('Adicionando ao carrinho:', payload);
23
+
24
+ var variantSku = payload.selectedIdentifier;
25
+
26
+ fetch('/cart/add.js', {
27
+ method: 'POST',
28
+ headers: {
29
+ 'Content-Type': 'application/json',
30
+ },
31
+ body: JSON.stringify({
32
+ items: [{
33
+ quantity: 1,
34
+ id: variantSku
35
+ }]
36
+ })
37
+ })
38
+ .then(function (response) {
39
+ return response.json();
40
+ })
41
+ .then(function (data) {
42
+ console.log('Produto adicionado:', data);
43
+ // document.dispatchEvent(new CustomEvent('cart:updated'));
44
+ })
45
+ .catch(function (error) {
46
+ console.error('Erro carrinho:', error);
47
+ });
48
+ });
49
+
50
+ mkfashion.onInteraction(function (data) {
51
+ console.log(data.category, data.action);
52
+ });
53
+
54
+ mkfashion.init({
55
+ projectId: projectid,
56
+ identifier: identifier,
57
+ target: '#mkfashion-container'
58
+ });
59
+ }
60
+
61
+ function waitForMkFashion() {
62
+ if (typeof mkfashion !== 'undefined') {
63
+ initMkFashion();
64
+ } else {
65
+ setTimeout(waitForMkFashion, 100);
66
+ }
67
+ }
68
+
69
+ if (document.readyState === "loading") {
70
+ document.addEventListener("DOMContentLoaded", waitForMkFashion);
71
+ } else {
72
+ waitForMkFashion();
73
+ }
74
+ })();
75
+ </script>
76
+
77
+ </body>
78
+
79
+ </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mkfashion-sdk",
3
- "version": "2.4.7",
3
+ "version": "2.4.9",
4
4
  "description": "SDK para integrar o provador virtual mKFashion com suporte a Wake Commerce",
5
5
  "main": "src/mkfashion.js",
6
6
  "scripts": {
package/src/mkfashion.js CHANGED
@@ -642,7 +642,7 @@ const mkfashion = {
642
642
  iframe.style.width = typeof width === 'number' ? `${width}px` : width
643
643
  iframe.style.height = typeof height === 'number' ? `${height}px` : height
644
644
  iframe.style.border = 'none'
645
- iframe.setAttribute('allow', 'camera *; microphone *')
645
+ iframe.setAttribute('allow', 'camera *; microphone *; web-share *')
646
646
  iframe.setAttribute('allowfullscreen', 'true')
647
647
  return iframe
648
648
  },
@@ -1009,8 +1009,9 @@ const mkfashion = {
1009
1009
 
1010
1010
  return this._el('button', {
1011
1011
  attrs: { type: 'button' },
1012
- style: `display: inline-flex; align-items: center; justify-content: center;
1013
- gap: 8px; padding: 8px; width: 238px; box-sizing: border-box;
1012
+ style: `display: flex; align-items: center; justify-content: center;
1013
+ gap: 8px; padding: 8px; width: 100%; max-width: 238px;
1014
+ box-sizing: border-box;
1014
1015
  background: ${c.bgColor};
1015
1016
  border: ${this._borderFromConfig(c)};
1016
1017
  border-radius: ${c.borderRadiusPx};
@@ -1124,7 +1125,7 @@ const mkfashion = {
1124
1125
 
1125
1126
  return this._el('div', {
1126
1127
  style: `display: flex; flex-direction: column; align-items: flex-start;
1127
- padding: 12px; width: 402px; min-height: 140px;
1128
+ padding: 12px; width: 100%; max-width: 402px; min-height: 140px;
1128
1129
  box-sizing: border-box;
1129
1130
  background: ${c.cardBgColor};
1130
1131
  border-radius: ${c.cardBorderRadiusPx};
package/test-e2e.html CHANGED
@@ -1,175 +1,175 @@
1
- <!DOCTYPE html>
2
- <html lang="pt-BR">
3
- <head>
4
- <meta charset="UTF-8">
5
- <title>mKFashion SDK — E2E Test</title>
6
- <script src="./src/mkfashion.js"></script>
7
- <style>
8
- body { font-family: -apple-system, BlinkMacSystemFont, sans-serif; margin: 24px; max-width: 900px; }
9
- .test { margin-bottom: 16px; padding: 12px; background: #f5f5f5; border-radius: 6px; border-left: 4px solid #999; }
10
- .test.pass { border-color: #16a34a; background: #ecfdf5; }
11
- .test.fail { border-color: #dc2626; background: #fef2f2; }
12
- .test h3 { margin: 0 0 6px; font-size: 14px; }
13
- .test pre { margin: 0; font-size: 11px; white-space: pre-wrap; }
14
- .target { display: inline-block; margin: 0 8px; padding: 4px 8px; background: white; border: 1px dashed #ccc; }
15
- </style>
16
- </head>
17
- <body>
18
- <h2>mKFashion SDK — E2E Tests</h2>
19
-
20
- <div>
21
- <span>Container 1 (válido):</span><span class="target" id="target-valid"></span>
22
- <span>Container 2 (válido):</span><span class="target" id="target-2"></span>
23
- </div>
24
-
25
- <div id="output" style="margin-top: 24px;"></div>
26
-
27
- <script>
28
- const projectId = '69c56d5373ecdf64df48e330'
29
- const validSku = '000756397001'
30
- const invalidSku = '99999999999999'
31
- const output = document.getElementById('output')
32
-
33
- function log(name, passed, details) {
34
- const div = document.createElement('div')
35
- div.className = 'test ' + (passed ? 'pass' : 'fail')
36
- div.innerHTML = `<h3>${passed ? 'PASS' : 'FAIL'} — ${name}</h3><pre>${details}</pre>`
37
- output.appendChild(div)
38
- }
39
-
40
- function fmt(obj) {
41
- return JSON.stringify(obj, (k, v) => v instanceof HTMLElement ? `<${v.tagName.toLowerCase()}>` : v, 2)
42
- }
43
-
44
- async function run() {
45
- // ---- TEST 1: init com params completos e SKU válido ----
46
- const r1 = await mkfashion.init({
47
- projectId,
48
- identifier: validSku,
49
- target: '#target-valid'
50
- })
51
- log(
52
- 'init() com SKU válido → ok: true, reason: rendered',
53
- r1.ok === true && r1.reason === 'rendered' && r1.element instanceof HTMLElement,
54
- fmt(r1)
55
- )
56
-
57
- // ---- TEST 2: init sem target ----
58
- const r2 = await mkfashion.init({ projectId, identifier: validSku })
59
- log(
60
- 'init() sem target → ok: false, reason: missing_target',
61
- r2.ok === false && r2.reason === 'missing_target' && r2.element === null,
62
- fmt(r2)
63
- )
64
-
65
- // ---- TEST 3 (skipped): init sem projectId ----
66
- // Comportamento atual: _resolveProjectId silenciosamente faz fallback pro
67
- // projeto Gregory quando raw é falsy. Conhecido como débito técnico,
68
- // não testamos como "missing_projectId" aqui.
69
-
70
- // ---- TEST 4: init sem identifier ----
71
- const r4 = await mkfashion.init({ projectId, target: '#target-2' })
72
- log(
73
- 'init() sem identifier → ok: false, reason: missing_identifier',
74
- r4.ok === false && r4.reason === 'missing_identifier' && r4.element === null,
75
- fmt(r4)
76
- )
77
-
78
- // ---- TEST 5: init com target inexistente ----
79
- const r5 = await mkfashion.init({
80
- projectId,
81
- identifier: validSku,
82
- target: '#nao-existe'
83
- })
84
- log(
85
- 'init() com target inexistente → ok: false, reason: target_not_found',
86
- r5.ok === false && r5.reason === 'target_not_found' && r5.element === null,
87
- fmt(r5)
88
- )
89
-
90
- // ---- TEST 6: init com SKU indisponível ----
91
- const r6 = await mkfashion.init({
92
- projectId,
93
- identifier: invalidSku,
94
- target: '#target-2'
95
- })
96
- log(
97
- 'init() com SKU indisponível → ok: false, reason: unavailable',
98
- r6.ok === false && r6.reason === 'unavailable' && r6.element === null,
99
- fmt(r6)
100
- )
101
-
102
- // ---- TEST 7: addToCart callback é disparado via postMessage ----
103
- let cartPayload = null
104
- mkfashion.addToCart(payload => { cartPayload = payload })
105
-
106
- // Abre o modal pra acionar o setup do message listener
107
- await mkfashion.open({ projectId, identifier: validSku })
108
- // Fecha imediatamente (listener fica armado)
109
- mkfashion.close()
110
-
111
- // Simula iframe enviando add_to_cart
112
- const fakePayload = {
113
- size: 'M',
114
- product: {
115
- name: 'Afrik - Óculos de Sol',
116
- price: 299.90,
117
- variantSku: 'SKU-VAR-M',
118
- produtoVarianteId: '12345',
119
- productUrl: 'https://example.com/produto/afrik',
120
- tryonImageUrl: 'https://cdn.example.com/tryon/abc.jpg'
121
- }
122
- }
123
- window.postMessage({
124
- source: 'mkfashion-app',
125
- action: 'add_to_cart',
126
- data: fakePayload
127
- }, '*')
128
-
129
- // Aguarda o handler async processar
130
- await new Promise(r => setTimeout(r, 100))
131
-
132
- log(
133
- 'addToCart callback dispara com payload simplificado (não-Gregory)',
134
- cartPayload !== null
135
- && cartPayload.mainIdentifier === validSku
136
- && cartPayload.selectedIdentifier === 'SKU-VAR-M'
137
- && cartPayload.name === 'Afrik - Óculos de Sol'
138
- && cartPayload.price === 299.90
139
- && cartPayload.selectedSize === 'M'
140
- && cartPayload.productUrl === 'https://example.com/produto/afrik',
141
- fmt(cartPayload)
142
- )
143
-
144
- // ---- TEST 8: onInteraction callback ----
145
- let interactionData = null
146
- mkfashion.onInteraction(data => { interactionData = data })
147
-
148
- window.postMessage({
149
- source: 'mkfashion-app',
150
- action: 'interaction',
151
- data: { category: 'try_on', action: 'photo_uploaded' }
152
- }, '*')
153
-
154
- await new Promise(r => setTimeout(r, 100))
155
-
156
- log(
157
- 'onInteraction callback dispara com category + action',
158
- interactionData !== null
159
- && interactionData.category === 'try_on'
160
- && interactionData.action === 'photo_uploaded',
161
- fmt(interactionData)
162
- )
163
-
164
- // ---- Marker pro screenshot saber que terminou ----
165
- document.title = 'DONE — ' + output.querySelectorAll('.test').length + ' tests'
166
- }
167
-
168
- if (typeof mkfashion !== 'undefined') {
169
- run().catch(e => log('Exception não tratada', false, e.message + '\n' + e.stack))
170
- } else {
171
- document.addEventListener('DOMContentLoaded', run)
172
- }
173
- </script>
174
- </body>
175
- </html>
1
+ <!DOCTYPE html>
2
+ <html lang="pt-BR">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>mKFashion SDK — E2E Test</title>
6
+ <script src="./src/mkfashion.js"></script>
7
+ <style>
8
+ body { font-family: -apple-system, BlinkMacSystemFont, sans-serif; margin: 24px; max-width: 900px; }
9
+ .test { margin-bottom: 16px; padding: 12px; background: #f5f5f5; border-radius: 6px; border-left: 4px solid #999; }
10
+ .test.pass { border-color: #16a34a; background: #ecfdf5; }
11
+ .test.fail { border-color: #dc2626; background: #fef2f2; }
12
+ .test h3 { margin: 0 0 6px; font-size: 14px; }
13
+ .test pre { margin: 0; font-size: 11px; white-space: pre-wrap; }
14
+ .target { display: inline-block; margin: 0 8px; padding: 4px 8px; background: white; border: 1px dashed #ccc; }
15
+ </style>
16
+ </head>
17
+ <body>
18
+ <h2>mKFashion SDK — E2E Tests</h2>
19
+
20
+ <div>
21
+ <span>Container 1 (válido):</span><span class="target" id="target-valid"></span>
22
+ <span>Container 2 (válido):</span><span class="target" id="target-2"></span>
23
+ </div>
24
+
25
+ <div id="output" style="margin-top: 24px;"></div>
26
+
27
+ <script>
28
+ const projectId = '69c56d5373ecdf64df48e330'
29
+ const validSku = '000756397001'
30
+ const invalidSku = '99999999999999'
31
+ const output = document.getElementById('output')
32
+
33
+ function log(name, passed, details) {
34
+ const div = document.createElement('div')
35
+ div.className = 'test ' + (passed ? 'pass' : 'fail')
36
+ div.innerHTML = `<h3>${passed ? 'PASS' : 'FAIL'} — ${name}</h3><pre>${details}</pre>`
37
+ output.appendChild(div)
38
+ }
39
+
40
+ function fmt(obj) {
41
+ return JSON.stringify(obj, (k, v) => v instanceof HTMLElement ? `<${v.tagName.toLowerCase()}>` : v, 2)
42
+ }
43
+
44
+ async function run() {
45
+ // ---- TEST 1: init com params completos e SKU válido ----
46
+ const r1 = await mkfashion.init({
47
+ projectId,
48
+ identifier: validSku,
49
+ target: '#target-valid'
50
+ })
51
+ log(
52
+ 'init() com SKU válido → ok: true, reason: rendered',
53
+ r1.ok === true && r1.reason === 'rendered' && r1.element instanceof HTMLElement,
54
+ fmt(r1)
55
+ )
56
+
57
+ // ---- TEST 2: init sem target ----
58
+ const r2 = await mkfashion.init({ projectId, identifier: validSku })
59
+ log(
60
+ 'init() sem target → ok: false, reason: missing_target',
61
+ r2.ok === false && r2.reason === 'missing_target' && r2.element === null,
62
+ fmt(r2)
63
+ )
64
+
65
+ // ---- TEST 3 (skipped): init sem projectId ----
66
+ // Comportamento atual: _resolveProjectId silenciosamente faz fallback pro
67
+ // projeto Gregory quando raw é falsy. Conhecido como débito técnico,
68
+ // não testamos como "missing_projectId" aqui.
69
+
70
+ // ---- TEST 4: init sem identifier ----
71
+ const r4 = await mkfashion.init({ projectId, target: '#target-2' })
72
+ log(
73
+ 'init() sem identifier → ok: false, reason: missing_identifier',
74
+ r4.ok === false && r4.reason === 'missing_identifier' && r4.element === null,
75
+ fmt(r4)
76
+ )
77
+
78
+ // ---- TEST 5: init com target inexistente ----
79
+ const r5 = await mkfashion.init({
80
+ projectId,
81
+ identifier: validSku,
82
+ target: '#nao-existe'
83
+ })
84
+ log(
85
+ 'init() com target inexistente → ok: false, reason: target_not_found',
86
+ r5.ok === false && r5.reason === 'target_not_found' && r5.element === null,
87
+ fmt(r5)
88
+ )
89
+
90
+ // ---- TEST 6: init com SKU indisponível ----
91
+ const r6 = await mkfashion.init({
92
+ projectId,
93
+ identifier: invalidSku,
94
+ target: '#target-2'
95
+ })
96
+ log(
97
+ 'init() com SKU indisponível → ok: false, reason: unavailable',
98
+ r6.ok === false && r6.reason === 'unavailable' && r6.element === null,
99
+ fmt(r6)
100
+ )
101
+
102
+ // ---- TEST 7: addToCart callback é disparado via postMessage ----
103
+ let cartPayload = null
104
+ mkfashion.addToCart(payload => { cartPayload = payload })
105
+
106
+ // Abre o modal pra acionar o setup do message listener
107
+ await mkfashion.open({ projectId, identifier: validSku })
108
+ // Fecha imediatamente (listener fica armado)
109
+ mkfashion.close()
110
+
111
+ // Simula iframe enviando add_to_cart
112
+ const fakePayload = {
113
+ size: 'M',
114
+ product: {
115
+ name: 'Afrik - Óculos de Sol',
116
+ price: 299.90,
117
+ variantSku: 'SKU-VAR-M',
118
+ produtoVarianteId: '12345',
119
+ productUrl: 'https://example.com/produto/afrik',
120
+ tryonImageUrl: 'https://cdn.example.com/tryon/abc.jpg'
121
+ }
122
+ }
123
+ window.postMessage({
124
+ source: 'mkfashion-app',
125
+ action: 'add_to_cart',
126
+ data: fakePayload
127
+ }, '*')
128
+
129
+ // Aguarda o handler async processar
130
+ await new Promise(r => setTimeout(r, 100))
131
+
132
+ log(
133
+ 'addToCart callback dispara com payload simplificado (não-Gregory)',
134
+ cartPayload !== null
135
+ && cartPayload.mainIdentifier === validSku
136
+ && cartPayload.selectedIdentifier === 'SKU-VAR-M'
137
+ && cartPayload.name === 'Afrik - Óculos de Sol'
138
+ && cartPayload.price === 299.90
139
+ && cartPayload.selectedSize === 'M'
140
+ && cartPayload.productUrl === 'https://example.com/produto/afrik',
141
+ fmt(cartPayload)
142
+ )
143
+
144
+ // ---- TEST 8: onInteraction callback ----
145
+ let interactionData = null
146
+ mkfashion.onInteraction(data => { interactionData = data })
147
+
148
+ window.postMessage({
149
+ source: 'mkfashion-app',
150
+ action: 'interaction',
151
+ data: { category: 'try_on', action: 'photo_uploaded' }
152
+ }, '*')
153
+
154
+ await new Promise(r => setTimeout(r, 100))
155
+
156
+ log(
157
+ 'onInteraction callback dispara com category + action',
158
+ interactionData !== null
159
+ && interactionData.category === 'try_on'
160
+ && interactionData.action === 'photo_uploaded',
161
+ fmt(interactionData)
162
+ )
163
+
164
+ // ---- Marker pro screenshot saber que terminou ----
165
+ document.title = 'DONE — ' + output.querySelectorAll('.test').length + ' tests'
166
+ }
167
+
168
+ if (typeof mkfashion !== 'undefined') {
169
+ run().catch(e => log('Exception não tratada', false, e.message + '\n' + e.stack))
170
+ } else {
171
+ document.addEventListener('DOMContentLoaded', run)
172
+ }
173
+ </script>
174
+ </body>
175
+ </html>
@@ -0,0 +1,45 @@
1
+ <!DOCTYPE html>
2
+ <html lang="pt-BR">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Test — Responsividade do botão</title>
6
+ <script src="./src/mkfashion.js"></script>
7
+ <style>
8
+ body { font-family: system-ui, sans-serif; margin: 24px; }
9
+ h3 { margin: 20px 0 8px; font-size: 13px; color: #444; }
10
+ .box { background: #fef3c7; padding: 8px; margin-bottom: 8px; }
11
+ </style>
12
+ </head>
13
+ <body>
14
+
15
+ <h3>Container 800px (mais largo que o max-width)</h3>
16
+ <div class="box" style="width: 800px;">
17
+ <div id="c1"></div>
18
+ </div>
19
+
20
+ <h3>Container 300px (menor que 402px do card)</h3>
21
+ <div class="box" style="width: 300px;">
22
+ <div id="c2"></div>
23
+ </div>
24
+
25
+ <h3>Container 180px (menor que 238px do simples)</h3>
26
+ <div class="box" style="width: 180px;">
27
+ <div id="c3"></div>
28
+ </div>
29
+
30
+ <h3>Container sem width (herda do pai)</h3>
31
+ <div class="box">
32
+ <div id="c4"></div>
33
+ </div>
34
+
35
+ <script>
36
+ var pid = '69c56d5373ecdf64df48e330'
37
+ var sku = '000756397001'
38
+ // Configura os 4 inits — todos pra mesma config (gregory-card no momento)
39
+ mkfashion.init({ projectId: pid, identifier: sku, target: '#c1' })
40
+ mkfashion.init({ projectId: pid, identifier: sku, target: '#c2' })
41
+ mkfashion.init({ projectId: pid, identifier: sku, target: '#c3' })
42
+ mkfashion.init({ projectId: pid, identifier: sku, target: '#c4' })
43
+ </script>
44
+ </body>
45
+ </html>
Binary file
Binary file