@dile/crud 2.2.0 → 2.2.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.
@@ -1 +1,2 @@
1
1
  export { DileManyRelation } from './src/DileManyRelation.js';
2
+ export { DileManyRelationOverlay } from './src/DileManyRelationOverlay.js';
@@ -0,0 +1,5 @@
1
+ import { DileManyRelationOverlay } from './src/DileManyRelationOverlay.js';
2
+
3
+ if (!customElements.get('dile-many-relation-overlay')) {
4
+ customElements.define('dile-many-relation-overlay', DileManyRelationOverlay);
5
+ }
@@ -0,0 +1,101 @@
1
+ import { describe, it, expect, afterEach, vi } from 'vitest';
2
+ import './many-relation.js';
3
+ import './many-relation-overlay.js';
4
+
5
+ const VARIANTS = [
6
+ { tag: 'dile-many-relation', selectTag: 'dile-ajax-select-crud' },
7
+ { tag: 'dile-many-relation-overlay', selectTag: 'dile-ajax-select-crud-overlay' },
8
+ ];
9
+
10
+ describe.each(VARIANTS)('$tag (select: $selectTag)', ({ tag, selectTag }) => {
11
+ afterEach(() => {
12
+ document.body.innerHTML = '';
13
+ delete window.axiosInstance;
14
+ });
15
+
16
+ function mockAxios({ get = vi.fn(), post = vi.fn(), delete: del = vi.fn() } = {}) {
17
+ window.axiosInstance = { get, post, delete: del };
18
+ return window.axiosInstance;
19
+ }
20
+
21
+ async function renderManyRelation(attrs = '') {
22
+ document.body.innerHTML = `
23
+ <${tag}
24
+ endpointGet="/api/tags"
25
+ endpointList="/api/board-games/1/tags"
26
+ endpointAdd="/api/board-games/1/tags"
27
+ endpointRemove="/api/board-games/1/tags"
28
+ idProperty="id"
29
+ displayProperty="name"
30
+ ${attrs}
31
+ ></${tag}>
32
+ `;
33
+ const el = document.body.querySelector(tag);
34
+ await el.updateComplete;
35
+ return el;
36
+ }
37
+
38
+ function select(el) {
39
+ return el.shadowRoot.getElementById('theselect');
40
+ }
41
+
42
+ it(`renders a ${selectTag} as the select control`, async () => {
43
+ mockAxios({ get: vi.fn(() => Promise.resolve({ status: 200, data: [] })) });
44
+ const el = await renderManyRelation();
45
+
46
+ const theselect = select(el);
47
+ expect(theselect).toBeTruthy();
48
+ expect(theselect.tagName.toLowerCase()).toBe(selectTag);
49
+ });
50
+
51
+ it('loads the related items list from endpointList on connect', async () => {
52
+ const get = vi.fn(() =>
53
+ Promise.resolve({ status: 200, data: { data: [{ id: 1, name: 'Strategy' }] } })
54
+ );
55
+ mockAxios({ get });
56
+ const el = await renderManyRelation('loadFromEndpoint');
57
+ await vi.waitFor(() => expect(el._items).toEqual([{ id: 1, name: 'Strategy' }]));
58
+
59
+ expect(get).toHaveBeenCalledWith('/api/board-games/1/tags', { params: undefined });
60
+ });
61
+
62
+ it('adds the item selected through the select control', async () => {
63
+ const post = vi.fn(() => Promise.resolve({ status: 201, data: {} }));
64
+ const get = vi.fn(() => Promise.resolve({ status: 200, data: { data: [] } }));
65
+ mockAxios({ post, get });
66
+ const el = await renderManyRelation();
67
+
68
+ select(el).dispatchEvent(
69
+ new CustomEvent('element-changed', { detail: { value: '5' } })
70
+ );
71
+ await el.updateComplete;
72
+ expect(el._selectedId).toBe('5');
73
+
74
+ el.shadowRoot.querySelector('button.add-btn').click();
75
+ // adding successfully triggers a list auto-refresh; wait it out before mocks are torn down
76
+ await vi.waitFor(() => expect(get).toHaveBeenCalled());
77
+
78
+ expect(post).toHaveBeenCalledWith('/api/board-games/1/tags', { id: '5' }, undefined);
79
+ });
80
+
81
+ it('removes an item and dispatches many-relation-remove-success', async () => {
82
+ const del = vi.fn(() => Promise.resolve({ status: 200, data: {} }));
83
+ const get = vi.fn(() => Promise.resolve({ status: 200, data: { data: [] } }));
84
+ mockAxios({ get, delete: del });
85
+ const el = await renderManyRelation();
86
+ el.relatedItems = [{ id: 9, name: 'Party' }];
87
+
88
+ const removeListener = vi.fn();
89
+ el.addEventListener('many-relation-remove-success', removeListener);
90
+
91
+ await vi.waitFor(() =>
92
+ expect(el.shadowRoot.querySelector('button.remove-btn')).toBeTruthy()
93
+ );
94
+ el.shadowRoot.querySelector('button.remove-btn').click();
95
+ await vi.waitFor(() => expect(removeListener).toHaveBeenCalled());
96
+ // wait out the list auto-refresh triggered by the removal before mocks are torn down
97
+ await vi.waitFor(() => expect(get).toHaveBeenCalled());
98
+
99
+ expect(del).toHaveBeenCalledWith('/api/board-games/1/tags/9', {}, undefined);
100
+ });
101
+ });
@@ -1,4 +1,5 @@
1
- import { LitElement, html, css } from 'lit';
1
+ import { LitElement, css } from 'lit';
2
+ import { html, unsafeStatic } from 'lit/static-html.js';
2
3
  import { DileI18nMixin } from '../../../lib/DileI18nMixin.js';
3
4
  import { addIcon, clearIcon } from '@dile/icons';
4
5
  import '../../ajax/ajax.js';
@@ -9,13 +10,15 @@ import '@dile/ui/components/input/input-message.js';
9
10
  import { labelStyles } from '@dile/ui/components/input/src/label-styles.js';
10
11
 
11
12
  export class DileManyRelation extends DileI18nMixin(LitElement) {
13
+ static selectTag = 'dile-ajax-select-crud';
14
+
12
15
  static styles = [
13
16
  labelStyles,
14
17
  css`
15
18
  :host {
16
19
  display: block;
17
20
  }
18
- dile-ajax-select-crud{
21
+ #theselect {
19
22
  margin-bottom: 0;
20
23
  }
21
24
  .relation-item {
@@ -61,7 +64,7 @@ export class DileManyRelation extends DileI18nMixin(LitElement) {
61
64
  gap: 0.5rem;
62
65
  margin-bottom: 0.5rem;
63
66
  }
64
- .add-row dile-ajax-select-crud {
67
+ .add-row #theselect {
65
68
  flex: 1;
66
69
  }
67
70
  button.add-btn dile-icon {
@@ -159,6 +162,7 @@ export class DileManyRelation extends DileI18nMixin(LitElement) {
159
162
  }
160
163
 
161
164
  render() {
165
+ const selectTag = unsafeStatic(this.constructor.selectTag);
162
166
  return html`
163
167
  <dile-ajax
164
168
  id="ajaxlist"
@@ -186,7 +190,7 @@ export class DileManyRelation extends DileI18nMixin(LitElement) {
186
190
  : ""
187
191
  }
188
192
  <div class="add-row">
189
- <dile-ajax-select-crud
193
+ <${selectTag}
190
194
  id="theselect"
191
195
  endpoint="${this.endpointGet}"
192
196
  displayProperty="${this.displayProperty}"
@@ -200,7 +204,7 @@ export class DileManyRelation extends DileI18nMixin(LitElement) {
200
204
  .getSelectResultList="${this.getSelectResultList}"
201
205
  language="${this.language}"
202
206
  @element-changed="${this._onSelectChanged}"
203
- ></dile-ajax-select-crud>
207
+ ></${selectTag}>
204
208
  ${!this.addOnSelect ? html`
205
209
  <button
206
210
  class="add-btn"
@@ -0,0 +1,6 @@
1
+ import { DileManyRelation } from './DileManyRelation.js';
2
+ import '../../ajax-select-crud/ajax-select-crud-overlay.js';
3
+
4
+ export class DileManyRelationOverlay extends DileManyRelation {
5
+ static selectTag = 'dile-ajax-select-crud-overlay';
6
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dile/crud",
3
- "version": "2.2.0",
3
+ "version": "2.2.1",
4
4
  "description": "Components to create a generic crud system based on Web Components and Lit",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -25,12 +25,12 @@
25
25
  },
26
26
  "homepage": "https://dile-components.com/",
27
27
  "dependencies": {
28
- "@dile/ui": "^3.5.0",
28
+ "@dile/ui": "^3.5.1",
29
29
  "axios": "^1.19.0",
30
30
  "lit": "^2.7.0 || ^3.0.0"
31
31
  },
32
32
  "publishConfig": {
33
33
  "access": "public"
34
34
  },
35
- "gitHead": "817f0dfc3c345957ae7a63c113e22aa0f80a773f"
35
+ "gitHead": "7bcf203fb23acc24867e9f3df4f3ca2367eabd97"
36
36
  }