Skip to content

Commit

Permalink
fix(vdom): render <input list> as attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
manucorporat committed Oct 10, 2019
1 parent 25f60fe commit 73ea50e
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 59 deletions.
10 changes: 9 additions & 1 deletion src/mock-doc/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,16 @@ class MockInputElement extends MockHTMLElement {
constructor(ownerDocument: any) {
super(ownerDocument, 'input');
}

get list() {
const listId = this.getAttribute('list');
if (listId) {
return (this.ownerDocument as Document).getElementById(listId);
}
return null;
}
}

patchPropAttributes(MockInputElement.prototype, {
accept: String,
autocomplete: String,
Expand All @@ -132,7 +141,6 @@ patchPropAttributes(MockInputElement.prototype, {
formtarget: String,
height: Number,
inputmode: String,
list: String,
max: String,
maxLength: Number,
min: String,
Expand Down
133 changes: 79 additions & 54 deletions src/mock-doc/test/element.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,69 +53,72 @@ describe('element', () => {
expect(elm).toEqualHtml(`<meta content="updated" id="test">`);
});

it('document.styleSheets', () => {
expect(document.styleSheets).toEqual([]);
const style = document.createElement('style');
document.head.appendChild(style);
expect(document.styleSheets).toEqual([style]);
});
describe('document', () => {

it('document.forms', () => {
expect(document.forms).toEqual([]);
const form = document.createElement('form');
document.head.appendChild(form);
expect(document.forms).toEqual([form]);
});
it('styleSheets', () => {
expect(document.styleSheets).toEqual([]);
const style = document.createElement('style');
document.head.appendChild(style);
expect(document.styleSheets).toEqual([style]);
});

it('document.scripts', () => {
expect(document.scripts).toEqual([]);
const script = document.createElement('script');
document.head.appendChild(script);
expect(document.scripts).toEqual([script]);
});
it('forms', () => {
expect(document.forms).toEqual([]);
const form = document.createElement('form');
document.head.appendChild(form);
expect(document.forms).toEqual([form]);
});

it('document.images', () => {
expect(document.images).toEqual([]);
const img = document.createElement('img');
document.head.appendChild(img);
expect(document.images).toEqual([img]);
});
it('scripts', () => {
expect(document.scripts).toEqual([]);
const script = document.createElement('script');
document.head.appendChild(script);
expect(document.scripts).toEqual([script]);
});

it('document.scrollingElement', () => {
expect(document.scrollingElement).toBe(document.documentElement);
});
it('images', () => {
expect(document.images).toEqual([]);
const img = document.createElement('img');
document.head.appendChild(img);
expect(document.images).toEqual([img]);
});

it('document.title', () => {
document.title = 'Hello Title';
expect(document.title).toBe('Hello Title');
it('scrollingElement', () => {
expect(document.scrollingElement).toBe(document.documentElement);
});

const titleElm = document.head.querySelector('title');
expect(titleElm.textContent).toBe('Hello Title');
expect(titleElm.text).toBe('Hello Title');
it('title', () => {
document.title = 'Hello Title';
expect(document.title).toBe('Hello Title');

titleElm.text = 'Hello Text';
expect(document.title).toBe('Hello Text');
expect(titleElm.text).toBe('Hello Text');
expect(titleElm.textContent).toBe('Hello Text');
});
const titleElm = document.head.querySelector('title');
expect(titleElm.textContent).toBe('Hello Title');
expect(titleElm.text).toBe('Hello Title');

it('document.baseURI', () => {
const win = new MockWindow(`
<html>
<head>
<base href="/en">
titleElm.text = 'Hello Text';
expect(document.title).toBe('Hello Text');
expect(titleElm.text).toBe('Hello Text');
expect(titleElm.textContent).toBe('Hello Text');
});

it('document.baseURI', () => {
const win = new MockWindow(`
<html>
<head>
<base href="/en">
</head>
</head>
</head>
`);
win.location.href = 'http://stenciljs.com/path/to/page';
expect(win.document.baseURI).toBe('http://stenciljs.com/en');
expect(win.document.URL).toBe('http://stenciljs.com/path/to/page');
expect(win.document.location.href).toBe('http://stenciljs.com/path/to/page');

win.document.querySelector('base').remove();
expect(win.document.baseURI).toBe('http://stenciljs.com/path/to/page');
expect(win.document.URL).toBe('http://stenciljs.com/path/to/page');
expect(win.document.location.href).toBe('http://stenciljs.com/path/to/page');
`);
win.location.href = 'http://stenciljs.com/path/to/page';
expect(win.document.baseURI).toBe('http://stenciljs.com/en');
expect(win.document.URL).toBe('http://stenciljs.com/path/to/page');
expect(win.document.location.href).toBe('http://stenciljs.com/path/to/page');

win.document.querySelector('base').remove();
expect(win.document.baseURI).toBe('http://stenciljs.com/path/to/page');
expect(win.document.URL).toBe('http://stenciljs.com/path/to/page');
expect(win.document.location.href).toBe('http://stenciljs.com/path/to/page');
});
});

describe('isConnected', () => {
Expand Down Expand Up @@ -284,6 +287,28 @@ describe('element', () => {
});
});

describe('input', () => {
it('list is readonly prop', () => {
const input = doc.createElement('input');
const list = doc.createElement('datalist');
list.id = 'my-list';
doc.body.append(input, list);
expect(input.list).toEqual(null);

// it's readonly
expect(() => input.list = 'my-list').toThrow();
expect(input.list).toEqual(null);

// finds list
input.setAttribute('list', 'my-list');
expect(input.list).toEqual(list);

// unknown id
input.setAttribute('list', 'unknown');
expect(input.list).toEqual(null);
});
});

describe('attributes', () => {
it('attributes are case sensible in Element', () => {
const element = new MockElement(doc, 'div');
Expand Down
6 changes: 4 additions & 2 deletions src/runtime/test/render-vdom.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,7 @@ describe('render-vdom', () => {
<input type='password' />
<input type='email' />
<input type='date' />
<input list='my-list' />
</Host>
);
}
Expand All @@ -595,13 +596,14 @@ describe('render-vdom', () => {
});
expect(root).toEqualHtml(`
<cmp-a>
<button type='button'></button>
<button type='submit'></button>
<button type=\"button\"></button>
<button type=\"submit\"></button>
<input type=\"text\" value=\"\">
<input type=\"number\">
<input type=\"password\">
<input type=\"email\">
<input type=\"date\">
<input list=\"my-list\" />
</cmp-a>
`);
});
Expand Down
6 changes: 4 additions & 2 deletions src/runtime/vdom/set-accessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,10 @@ export const setAccessor = (elm: HTMLElement, memberName: string, oldValue: any,
let n = newValue == null ? '' : newValue;

// Workaround for Safari, moving the <input> caret when re-assigning the same valued
// tslint:disable-next-line: triple-equals
if (oldValue == null || (elm as any)[memberName] != n) {
if (memberName === 'list') {
isProp = false;
// tslint:disable-next-line: triple-equals
} else if (oldValue == null || (elm as any)[memberName] != n) {
(elm as any)[memberName] = n;
}
} else {
Expand Down

0 comments on commit 73ea50e

Please sign in to comment.