diff --git a/libraries/__shared__/tests/package-lock.json b/libraries/__shared__/tests/package-lock.json new file mode 100644 index 0000000000..f88209ad10 --- /dev/null +++ b/libraries/__shared__/tests/package-lock.json @@ -0,0 +1,111 @@ +{ + "name": "tests", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "tests", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "chai": "4.3.10" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/chai": { + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", + "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + } + } +} diff --git a/libraries/__shared__/tests/package.json b/libraries/__shared__/tests/package.json new file mode 100644 index 0000000000..322556cbba --- /dev/null +++ b/libraries/__shared__/tests/package.json @@ -0,0 +1,10 @@ +{ + "name": "tests", + "version": "1.0.0", + "description": "", + "author": "", + "license": "ISC", + "devDependencies": { + "chai": "4.3.10" + } +} diff --git a/libraries/__shared__/tests/src/advanced-tests.js b/libraries/__shared__/tests/src/advanced-tests.js new file mode 100644 index 0000000000..6bd3cf9037 --- /dev/null +++ b/libraries/__shared__/tests/src/advanced-tests.js @@ -0,0 +1,107 @@ +/** + * @license + * Copyright 2017 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect } from 'chai' + + +function skip() { + this.skip(); + return {}; +} +export default function ( + { + renderComponentWithProperties = skip, + renderComponentWithDeclarativeEvent = skip + } +) { + + + describe('advanced support', function () { + + describe('attributes and properties', function () { + it('will pass array data as a property', async function () { + this.weight = 2 + const { wc } = await renderComponentWithProperties.call(this) + let data = wc.arr + expect(data).to.eql(['c', 'u', 's', 't', 'o', 'm']) + }) + + it('will pass object data as a property', async function () { + this.weight = 2 + const { wc } = await renderComponentWithProperties.call(this) + let data = wc.obj + expect(data).to.eql({org: 'webcomponents', repo: 'custom-elements-everywhere'}) + }) + + it('will pass object data to a camelCase-named property', async function () { + this.weight = 2 + const { wc } = await renderComponentWithProperties.call(this) + let data = wc.camelCaseObj; + expect(data).to.eql({label: "passed"}); + }) + + }) + + describe('events', function () { + it('can declaratively listen to a lowercase DOM event dispatched by a Custom Element', async function () { + this.weight = 2 + const { wc, click = wc.click.bind(wc), root = document } = await renderComponentWithDeclarativeEvent.call(this) + expect(wc).to.exist + let handled = root.querySelector('#lowercase') + expect(handled.textContent).to.eql('false') + await click() + expect(handled.textContent).to.eql('true') + }) + + it('can declaratively listen to a kebab-case DOM event dispatched by a Custom Element', async function () { + this.weight = 1 + const { wc, click = wc.click.bind(wc), root = document } = await renderComponentWithDeclarativeEvent.call(this) + let handled = root.querySelector('#kebab') + expect(handled.textContent).to.eql('false') + await click() + expect(handled.textContent).to.eql('true') + }) + + it('can declaratively listen to a camelCase DOM event dispatched by a Custom Element', async function () { + this.weight = 1 + const { wc, click = wc.click.bind(wc), root = document } = await renderComponentWithDeclarativeEvent.call(this) + let handled = root.querySelector('#camel') + expect(handled.textContent).to.eql('false') + await click() + expect(handled.textContent).to.eql('true') + }) + + it('can declaratively listen to a CAPScase DOM event dispatched by a Custom Element', async function () { + this.weight = 1 + const { wc, click = wc.click.bind(wc), root = document } = await renderComponentWithDeclarativeEvent.call(this) + let handled = root.querySelector('#caps') + expect(handled.textContent).to.eql('false') + await click() + expect(handled.textContent).to.eql('true') + }) + + it('can declaratively listen to a PascalCase DOM event dispatched by a Custom Element', async function () { + this.weight = 1 + const { wc, click = wc.click.bind(wc), root = document } = await renderComponentWithDeclarativeEvent.call(this) + let handled = root.querySelector('#pascal') + expect(handled.textContent).to.eql('false') + await click() + expect(handled.textContent).to.eql('true') + }) + }) + }) +} diff --git a/libraries/__shared__/tests/src/basic-tests.js b/libraries/__shared__/tests/src/basic-tests.js new file mode 100644 index 0000000000..ad2ac649c6 --- /dev/null +++ b/libraries/__shared__/tests/src/basic-tests.js @@ -0,0 +1,118 @@ +/** + * @license + * Copyright 2017 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {expect} from 'chai' + +function skip() { + this.skip(); + return {}; +} + +export default function ( + { + renderComponentWithoutChildren = skip, + renderComponentWithChildren = skip, + renderComponentWithChildrenRerender = skip, + renderComponentWithDifferentViews = skip, + renderComponentWithProperties = skip, + renderComponentWithImperativeEvent = skip, + }) { + + describe('basic support', function () { + + describe('no children', function () { + it('can display a Custom Element with no children', async function () { + this.weight = 3 + const { wc } = await renderComponentWithoutChildren.call(this); + expect(wc).to.exist + }) + }) + + describe('with children', function () { + function expectHasChildren(wc) { + expect(wc).to.exist + let shadowRoot = wc.shadowRoot + let heading = shadowRoot.querySelector('h1') + expect(heading).to.exist + expect(heading.textContent).to.eql('Test h1') + let paragraph = shadowRoot.querySelector('p') + expect(paragraph).to.exist + expect(paragraph.textContent).to.eql('Test p') + } + + it('can display a Custom Element with children in a Shadow Root', async function () { + this.weight = 3 + const { wc } = await renderComponentWithChildren.call(this); + expectHasChildren(wc) + }) + + it('can display a Custom Element with children in a Shadow Root and pass in Light DOM children', async function () { + this.weight = 3 + const { wc } = await renderComponentWithChildrenRerender.call(this); + expectHasChildren(wc) + expect(wc.textContent.includes('2')).to.be.true + }) + + it('can display a Custom Element with children in the Shadow DOM and handle hiding and showing the element', async function () { + this.weight = 3 + const { wc, toggle, root = document } = await renderComponentWithDifferentViews.call(this); + expectHasChildren(wc) + await toggle() + const dummy = root.querySelector('#dummy') + expect(dummy).to.exist + expect(dummy.textContent).to.eql('Dummy view') + await toggle() + expectHasChildren(wc) + }) + }) + + describe('attributes and properties', function () { + it('will pass boolean data as either an attribute or a property', async function () { + this.weight = 3 + const { wc } = await renderComponentWithProperties.call(this); + let data = wc.bool || wc.hasAttribute('bool') + expect(data).to.be.true + }) + + it('will pass numeric data as either an attribute or a property', async function () { + this.weight = 3 + const { wc } = await renderComponentWithProperties.call(this); + let data = wc.num || wc.getAttribute('num') + expect(parseInt(data, 10)).to.eql(42) + }) + + it('will pass string data as either an attribute or a property', async function () { + this.weight = 3 + const { wc } = await renderComponentWithProperties.call(this); + let data = wc.str || wc.getAttribute('str') + expect(data).to.eql('custom') + }) + }) + + describe('events', async function () { + it('can imperatively listen to a DOM event dispatched by a Custom Element', async function () { + this.weight = 3 + const { wc, click = wc.click.bind(wc), root = document } = await renderComponentWithImperativeEvent.call(this) + expect(wc).to.exist + let handled = root.querySelector('#handled') + expect(handled.textContent).to.eql('false') + await click() + expect(handled.textContent).to.eql('true') + }) + }) + }) +} \ No newline at end of file diff --git a/libraries/angular/karma.conf.js b/libraries/angular/karma.conf.js index f93961ff31..2f285bd501 100644 --- a/libraries/angular/karma.conf.js +++ b/libraries/angular/karma.conf.js @@ -43,10 +43,10 @@ module.exports = function (config) { // RxJs. { pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false }, { pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false }, - 'tests.webpack.ts' + 'tests.webpack.js' ], preprocessors: { - 'tests.webpack.ts': ['webpack', 'sourcemap'] // preprocess with webpack and our sourcemap loader + 'tests.webpack.js': ['webpack', 'sourcemap'] // preprocess with webpack and our sourcemap loader }, mime: { 'text/x-typescript': ['ts'] @@ -68,6 +68,7 @@ module.exports = function (config) { extensions: ['.js', '.ts'], modules: [ path.resolve(__dirname, '../__shared__/webcomponents/src'), + path.resolve(__dirname, '../__shared__/tests/src'), path.resolve(__dirname, './node_modules'), path.resolve(__dirname, '../../node_modules'), ] diff --git a/libraries/angular/package.json b/libraries/angular/package.json index 267b9694cb..1ee2e529ec 100644 --- a/libraries/angular/package.json +++ b/libraries/angular/package.json @@ -42,7 +42,7 @@ ], "files": [ "karma.conf.js", - "tests.webpack.ts", + "tests.webpack.js", "tsconfig.json", "src", "meta" diff --git a/libraries/angular/src/advanced-tests.js b/libraries/angular/src/advanced-tests.js deleted file mode 100644 index f0f516dec1..0000000000 --- a/libraries/angular/src/advanced-tests.js +++ /dev/null @@ -1,150 +0,0 @@ -/** - * @license - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core"; -import { TestBed } from "@angular/core/testing"; -import { By } from "@angular/platform-browser"; -import { expect } from "chai"; -import { - ComponentWithoutChildren, - ComponentWithChildren, - ComponentWithChildrenRerender, - ComponentWithDifferentViews, - ComponentWithProperties, - ComponentWithUnregistered, - ComponentWithImperativeEvent, - ComponentWithDeclarativeEvent -} from "./components"; - -beforeEach(function() { - TestBed.configureTestingModule({ - declarations: [ - ComponentWithoutChildren, - ComponentWithChildren, - ComponentWithChildrenRerender, - ComponentWithDifferentViews, - ComponentWithProperties, - ComponentWithUnregistered, - ComponentWithImperativeEvent, - ComponentWithDeclarativeEvent - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] - }); -}); - -describe("advanced support", function() { - - describe("attributes and properties", function() { - it("will pass array data as a property", function() { - this.weight = 2; - let fixture = TestBed.createComponent(ComponentWithProperties); - fixture.detectChanges(); - let root = fixture.debugElement.nativeElement; - let wc = root.querySelector("#wc"); - let data = wc.arr; - expect(data).to.eql(["A", "n", "g", "u", "l", "a", "r"]); - }); - - it("will pass object data as a property", function() { - this.weight = 2; - let fixture = TestBed.createComponent(ComponentWithProperties); - fixture.detectChanges(); - let root = fixture.debugElement.nativeElement; - let wc = root.querySelector("#wc"); - let data = wc.obj; - expect(data).to.eql({ org: "angular", repo: "angular" }); - }); - - it("will pass object data to a camelCase-named property", function() { - this.weight = 2; - let fixture = TestBed.createComponent(ComponentWithProperties); - fixture.detectChanges(); - let root = fixture.debugElement.nativeElement; - let wc = root.querySelector("#wc"); - let data = wc.camelCaseObj; - expect(data).to.eql({ label: "passed" }); - }); - }); - - describe("events", function() { - it("can declaratively listen to a lowercase DOM event dispatched by a Custom Element", function() { - this.weight = 2; - let fixture = TestBed.createComponent(ComponentWithDeclarativeEvent); - fixture.detectChanges(); - let root = fixture.debugElement.nativeElement; - let wc = root.querySelector("#wc"); - let handled = root.querySelector("#lowercase"); - expect(handled.textContent).to.eql("false"); - wc.click(); - fixture.detectChanges(); - expect(handled.textContent).to.eql("true"); - }); - - it("can declaratively listen to a kebab-case DOM event dispatched by a Custom Element", function() { - this.weight = 1; - let fixture = TestBed.createComponent(ComponentWithDeclarativeEvent); - fixture.detectChanges(); - let root = fixture.debugElement.nativeElement; - let wc = root.querySelector("#wc"); - let handled = root.querySelector("#kebab"); - expect(handled.textContent).to.eql("false"); - wc.click(); - fixture.detectChanges(); - expect(handled.textContent).to.eql("true"); - }); - - it("can declaratively listen to a camelCase DOM event dispatched by a Custom Element", function() { - this.weight = 1; - let fixture = TestBed.createComponent(ComponentWithDeclarativeEvent); - fixture.detectChanges(); - let root = fixture.debugElement.nativeElement; - let wc = root.querySelector("#wc"); - let handled = root.querySelector("#camel"); - expect(handled.textContent).to.eql("false"); - wc.click(); - fixture.detectChanges(); - expect(handled.textContent).to.eql("true"); - }); - - it("can declaratively listen to a CAPScase DOM event dispatched by a Custom Element", function() { - this.weight = 1; - let fixture = TestBed.createComponent(ComponentWithDeclarativeEvent); - fixture.detectChanges(); - let root = fixture.debugElement.nativeElement; - let wc = root.querySelector("#wc"); - let handled = root.querySelector("#caps"); - expect(handled.textContent).to.eql("false"); - wc.click(); - fixture.detectChanges(); - expect(handled.textContent).to.eql("true"); - }); - - it("can declaratively listen to a PascalCase DOM event dispatched by a Custom Element", function() { - this.weight = 1; - let fixture = TestBed.createComponent(ComponentWithDeclarativeEvent); - fixture.detectChanges(); - let root = fixture.debugElement.nativeElement; - let wc = root.querySelector("#wc"); - let handled = root.querySelector("#pascal"); - expect(handled.textContent).to.eql("false"); - wc.click(); - fixture.detectChanges(); - expect(handled.textContent).to.eql("true"); - }); - }); - -}); diff --git a/libraries/angular/src/basic-tests.js b/libraries/angular/src/basic-tests.js deleted file mode 100644 index 80dba3fd4a..0000000000 --- a/libraries/angular/src/basic-tests.js +++ /dev/null @@ -1,166 +0,0 @@ -/** - * @license - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core"; -import { TestBed } from "@angular/core/testing"; -import { By } from "@angular/platform-browser"; -import { expect } from "chai"; -import { - ComponentWithoutChildren, - ComponentWithChildren, - ComponentWithChildrenRerender, - ComponentWithDifferentViews, - ComponentWithProperties, - ComponentWithUnregistered, - ComponentWithImperativeEvent, - ComponentWithDeclarativeEvent -} from "./components"; - -beforeEach(function() { - TestBed.configureTestingModule({ - declarations: [ - ComponentWithoutChildren, - ComponentWithChildren, - ComponentWithChildrenRerender, - ComponentWithDifferentViews, - ComponentWithProperties, - ComponentWithUnregistered, - ComponentWithImperativeEvent, - ComponentWithDeclarativeEvent - ], - schemas: [CUSTOM_ELEMENTS_SCHEMA] - }); -}); - -describe("basic support", function() { - - describe("no children", function() { - it("can display a Custom Element with no children", function() { - this.weight = 3; - let fixture = TestBed.createComponent(ComponentWithoutChildren); - fixture.detectChanges(); - let el = fixture.debugElement.nativeElement; - let wc = el.querySelector("ce-without-children"); - expect(wc).to.exist; - }); - }); - - describe("with children", function() { - function expectHasChildren(wc) { - expect(wc).to.exist; - let shadowRoot = wc.shadowRoot; - let heading = shadowRoot.querySelector("h1"); - expect(heading).to.exist; - expect(heading.textContent).to.eql("Test h1"); - let paragraph = shadowRoot.querySelector("p"); - expect(paragraph).to.exist; - expect(paragraph.textContent).to.eql("Test p"); - } - - it("can display a Custom Element with children in a Shadow Root", function() { - this.weight = 3; - let fixture = TestBed.createComponent(ComponentWithChildren); - fixture.detectChanges(); - let root = fixture.debugElement.nativeElement; - let wc = root.querySelector("#wc"); - expectHasChildren(wc); - }); - - it("can display a Custom Element with children in a Shadow Root and pass in Light DOM children", function( - done - ) { - this.weight = 3; - let fixture = TestBed.createComponent(ComponentWithChildrenRerender); - fixture.detectChanges(); - setTimeout(function() { - fixture.detectChanges(); - let root = fixture.debugElement.nativeElement; - let wc = root.querySelector("#wc"); - expectHasChildren(wc); - expect(wc.textContent.includes("2")).to.be.true; - done(); - }, 1000); - }); - - it("can display a Custom Element with children in a Shadow Root and handle hiding and showing the element", function() { - this.weight = 3; - let fixture = TestBed.createComponent(ComponentWithDifferentViews); - fixture.detectChanges(); - let component = fixture.componentInstance; - let root = fixture.debugElement.nativeElement; - let wc = root.querySelector("#wc"); - expectHasChildren(wc); - component.toggle(); - fixture.detectChanges(); - let dummy = root.querySelector("#dummy"); - expect(dummy).to.exist; - expect(dummy.textContent).to.eql("Dummy view"); - component.toggle(); - fixture.detectChanges(); - wc = root.querySelector("#wc"); - expectHasChildren(wc); - }); - }); - - describe("attributes and properties", function() { - it("will pass boolean data as either an attribute or a property", function() { - this.weight = 3; - let fixture = TestBed.createComponent(ComponentWithProperties); - fixture.detectChanges(); - let root = fixture.debugElement.nativeElement; - let wc = root.querySelector("#wc"); - let data = wc.bool || wc.hasAttribute("bool"); - expect(data).to.be.true; - }); - - it("will pass numeric data as either an attribute or a property", function() { - this.weight = 3; - let fixture = TestBed.createComponent(ComponentWithProperties); - fixture.detectChanges(); - let root = fixture.debugElement.nativeElement; - let wc = root.querySelector("#wc"); - let data = wc.num || wc.getAttribute("num"); - expect(parseInt(data, 10)).to.eql(42); - }); - - it("will pass string data as either an attribute or a property", function() { - this.weight = 3; - let fixture = TestBed.createComponent(ComponentWithProperties); - fixture.detectChanges(); - let root = fixture.debugElement.nativeElement; - let wc = root.querySelector("#wc"); - let data = wc.str || wc.getAttribute("str"); - expect(data).to.eql("Angular"); - }); - }); - - describe("events", function() { - it("can imperatively listen to a DOM event dispatched by a Custom Element", function() { - this.weight = 3; - let fixture = TestBed.createComponent(ComponentWithImperativeEvent); - fixture.detectChanges(); - let root = fixture.debugElement.nativeElement; - let wc = root.querySelector("#wc"); - let handled = root.querySelector("#handled"); - expect(handled.textContent).to.eql("false"); - wc.click(); - fixture.detectChanges(); - expect(handled.textContent).to.eql("true"); - }); - }); - -}); diff --git a/libraries/angular/src/components.ts b/libraries/angular/src/components.ts index fbb4cfe45e..ba1a5f59cd 100644 --- a/libraries/angular/src/components.ts +++ b/libraries/angular/src/components.ts @@ -98,9 +98,9 @@ export class ComponentWithProperties { data = { bool: true, num: 42, - str: 'Angular', - arr: ['A', 'n', 'g', 'u', 'l', 'a', 'r'], - obj: { org: 'angular', repo: 'angular' }, + str: 'custom', + arr: ['c', 'u', 's', 't', 'o', 'm'], + obj: { org: 'webcomponents', repo: 'custom-elements-everywhere' }, camelCaseObj: { label: "passed" } } } diff --git a/libraries/angular/tests.webpack.js b/libraries/angular/tests.webpack.js new file mode 100644 index 0000000000..3d158f21a5 --- /dev/null +++ b/libraries/angular/tests.webpack.js @@ -0,0 +1,125 @@ +/** + * @license + * Copyright 2017 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import 'reflect-metadata/Reflect'; +import 'zone.js/dist/zone'; +import 'zone.js/dist/webapis-shadydom'; // https://github.com/angular/zone.js/pull/784 +import 'zone.js/dist/long-stack-trace-zone'; +import 'zone.js/dist/proxy'; +import 'zone.js/dist/sync-test'; +import 'zone.js/dist/mocha-patch'; +import 'zone.js/dist/async-test'; +import 'zone.js/dist/fake-async-test'; +import { getTestBed } from '@angular/core/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting +} from '@angular/platform-browser-dynamic/testing'; +import { CUSTOM_ELEMENTS_SCHEMA } from "@angular/core"; +import { + ComponentWithChildren, + ComponentWithChildrenRerender, ComponentWithDeclarativeEvent, + ComponentWithDifferentViews, ComponentWithImperativeEvent, + ComponentWithoutChildren, ComponentWithProperties, ComponentWithUnregistered +} from "./src/components"; + +import basicTests from "basic-tests"; +import advancedTests from "advanced-tests"; + + +// Prevent Karma from running prematurely. +__karma__.loaded = function () {}; + +// First, initialize the Angular testing environment. +getTestBed().initTestEnvironment( + BrowserDynamicTestingModule, + platformBrowserDynamicTesting() +); +// Run basic and advanced tests through Karma + + +beforeEach(function() { + getTestBed().configureTestingModule({ + declarations: [ + ComponentWithoutChildren, + ComponentWithChildren, + ComponentWithChildrenRerender, + ComponentWithDifferentViews, + ComponentWithProperties, + ComponentWithUnregistered, + ComponentWithImperativeEvent, + ComponentWithDeclarativeEvent + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA] + }); +}); + +function render(Component) { + const fixture = getTestBed().createComponent(Component); + fixture.detectChanges(); + const el = fixture.debugElement.nativeElement; + const wc = el.querySelector('#wc'); + return { wc, fixture } +} + +const renderers = { + renderComponentWithoutChildren() { + return render(ComponentWithoutChildren); + }, + renderComponentWithChildren() { + return render(ComponentWithChildren); + }, + async renderComponentWithChildrenRerender() { + const results = render(ComponentWithChildrenRerender); + await new Promise((r) => setTimeout(r, 1000)); + results.fixture.detectChanges(); + return results; + }, + renderComponentWithDifferentViews() { + const { wc, fixture } = render(ComponentWithDifferentViews); + function toggle() { + fixture.componentInstance.toggle(); + fixture.detectChanges(); + } + return { wc, fixture, toggle } + }, + renderComponentWithProperties() { + return render(ComponentWithProperties); + }, + renderComponentWithImperativeEvent() { + const { wc, fixture } = render(ComponentWithImperativeEvent); + function click() { + wc.click(); + fixture.detectChanges(); + } + return { wc, fixture, click }; + }, + renderComponentWithDeclarativeEvent() { + const { wc, fixture } = render(ComponentWithDeclarativeEvent); + function click() { + wc.click(); + fixture.detectChanges(); + } + return { wc, fixture, click }; + } +}; + +basicTests(renderers); +advancedTests(renderers); + +// Finally, start Karma to run the tests. +__karma__.start(); diff --git a/libraries/angular/tests.webpack.ts b/libraries/angular/tests.webpack.ts deleted file mode 100644 index f16e8cb48d..0000000000 --- a/libraries/angular/tests.webpack.ts +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @license - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import 'reflect-metadata/Reflect'; -import 'zone.js/dist/zone'; -import 'zone.js/dist/webapis-shadydom'; // https://github.com/angular/zone.js/pull/784 -import 'zone.js/dist/long-stack-trace-zone'; -import 'zone.js/dist/proxy'; -import 'zone.js/dist/sync-test'; -import 'zone.js/dist/mocha-patch'; -import 'zone.js/dist/async-test'; -import 'zone.js/dist/fake-async-test'; -import { getTestBed } from '@angular/core/testing'; -import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting -} from '@angular/platform-browser-dynamic/testing'; - -declare var __karma__: any; -declare var require: any; - -// Prevent Karma from running prematurely. -__karma__.loaded = function () {}; - -// First, initialize the Angular testing environment. -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting() -); -// Run basic and advanced tests through Karma -require('./src/basic-tests.js'); -require('./src/advanced-tests.js'); -// Finally, start Karma to run the tests. -__karma__.start(); diff --git a/libraries/angularjs/karma.conf.js b/libraries/angularjs/karma.conf.js index 942544d300..42910b893d 100644 --- a/libraries/angularjs/karma.conf.js +++ b/libraries/angularjs/karma.conf.js @@ -62,6 +62,7 @@ module.exports = function (config) { extensions: ['.js'], modules: [ path.resolve(__dirname, '../__shared__/webcomponents/src'), + path.resolve(__dirname, '../__shared__/tests/src'), path.resolve(__dirname, './node_modules'), path.resolve(__dirname, '../../node_modules'), ] diff --git a/libraries/angularjs/src/advanced-tests.js b/libraries/angularjs/src/advanced-tests.js deleted file mode 100644 index f0b98d8949..0000000000 --- a/libraries/angularjs/src/advanced-tests.js +++ /dev/null @@ -1,114 +0,0 @@ -import { expect } from "chai"; -import prodApp from "./app.module"; - -describe("advanced support", () => { - - beforeEach(angular.mock.module(prodApp)); - - let compile; - let scope; - let interval; - beforeEach( - inject(($compile, $rootScope, $interval) => { - compile = $compile; - scope = $rootScope.$new(); - interval = $interval; - }) - ); - - describe("attributes and properties", () => { - const prep = el => { - return compile(el)(scope)[0]; - } - - it("will pass array data as a property", function() { - this.weight = 2; - let root = prep("") - scope.$digest() - let wc = root.querySelector('#wc') - let data = wc.arr; - expect(data).to.eql(['A', 'n', 'g', 'u', 'l', 'a', 'r']); - }); - - it("will pass object data as a property", function() { - this.weight = 2; - let root = prep("") - scope.$digest() - let wc = root.querySelector('#wc') - let data = wc.obj; - expect(data).to.eql({ org: "angular", repo: "angular" }); - }); - - it("will pass object data to a camelCase-named property", function() { - this.weight = 2; - let root = prep("") - scope.$digest() - let wc = root.querySelector('#wc') - let data = wc.camelCaseObj; - expect(data).to.eql({ label: "passed" }); - }); - }); - - describe("events", () => { - it("can declaratively listen to a lowercase DOM event dispatched by a Custom Element", function() { - this.weight = 2; - const root = compile("")(scope)[0]; - scope.$digest(); - let wc = root.querySelector("#wc"); - let handled = root.querySelector("#lowercase"); - expect(handled.textContent).to.eql("false"); - wc.click(); - scope.$digest(); - expect(handled.textContent).to.eql("true"); - }); - - it("can declaratively listen to a kebab-case DOM event dispatched by a Custom Element", function() { - this.weight = 1; - const root = compile("")(scope)[0]; - scope.$digest(); - let wc = root.querySelector("#wc"); - let handled = root.querySelector("#kebab"); - expect(handled.textContent).to.eql("false"); - wc.click(); - scope.$digest(); - expect(handled.textContent).to.eql("true"); - }); - - it("can declaratively listen to a camelCase DOM event dispatched by a Custom Element", function() { - this.weight = 1; - const root = compile("")(scope)[0]; - scope.$digest(); - let wc = root.querySelector("#wc"); - let handled = root.querySelector("#camel"); - expect(handled.textContent).to.eql("false"); - wc.click(); - scope.$digest(); - expect(handled.textContent).to.eql("true"); - }); - - it("can declaratively listen to a CAPScase DOM event dispatched by a Custom Element", function() { - this.weight = 1; - const root = compile("")(scope)[0]; - scope.$digest(); - let wc = root.querySelector("#wc"); - let handled = root.querySelector("#caps"); - expect(handled.textContent).to.eql("false"); - wc.click(); - scope.$digest(); - expect(handled.textContent).to.eql("true"); - }); - - it("can declaratively listen to a PascalCase DOM event dispatched by a Custom Element", function() { - this.weight = 1; - const root = compile("")(scope)[0]; - scope.$digest(); - let wc = root.querySelector("#wc"); - let handled = root.querySelector("#pascal"); - expect(handled.textContent).to.eql("false"); - wc.click(); - scope.$digest(); - expect(handled.textContent).to.eql("true"); - }); - }); - -}); diff --git a/libraries/angularjs/src/basic-tests.js b/libraries/angularjs/src/basic-tests.js deleted file mode 100644 index f90ff3ab43..0000000000 --- a/libraries/angularjs/src/basic-tests.js +++ /dev/null @@ -1,130 +0,0 @@ -import { expect } from "chai"; -import prodApp from "./app.module"; - -describe("basic support", () => { - - beforeEach(angular.mock.module(prodApp)); - - let compile; - let scope; - let interval; - beforeEach( - inject(($compile, $rootScope, $interval) => { - compile = $compile; - scope = $rootScope; - interval = $interval; - }) - ); - - describe("no children", () => { - it("can display a CE with no children", function() { - this.weight = 3; - const comp = compile("")(scope); - const wc = comp[0].querySelector("ce-without-children"); - expect(wc).to.exist; - }); - }); - - describe("with children", () => { - const prep = el => { - return compile(el)(scope)[0]; - }; - function expectHasChildren(wc) { - expect(wc).to.exist; - let shadowRoot = wc.shadowRoot; - let heading = shadowRoot.querySelector("h1"); - expect(heading).to.exist; - expect(heading.textContent).to.eql("Test h1"); - let paragraph = shadowRoot.querySelector("p"); - expect(paragraph).to.exist; - expect(paragraph.textContent).to.eql("Test p"); - } - - it("can display a Custom Element with children in a Shadow Root", function() { - this.weight = 3; - const root = prep(""); - let wc = root.querySelector("#wc"); - expectHasChildren(wc); - }); - - it("can display a Custom Element with children in a Shadow Root and pass in Light DOM children", function() { - this.weight = 3; - const root = prep(""); - interval.flush(1000); - let wc = root.querySelector("#wc"); - expectHasChildren(wc); - expect(wc.textContent.includes("2")).to.be.true; - }); - - it("can display a Custom Element with children in a Shadow Root and handle hiding and showing the element", function() { - this.weight = 3; - scope.showWc = true; - const root = prep(``); - scope.$apply(); - let wc = root.querySelector("#wc"); - expectHasChildren(wc); - - scope.showWc = false; - scope.$apply(); - - let dummy = root.querySelector("#dummy"); - expect(dummy).to.exist; - expect(dummy.textContent).to.eql("Dummy view"); - - scope.showWc = true; - scope.$apply(); - - wc = root.querySelector("#wc"); - expectHasChildren(wc); - }); - }); - - describe("attributes and properties", function() { - let wc; - beforeEach(() => { - const comp = compile("")(scope); - scope.$digest(); - - wc = comp[0].querySelector("#wc"); - }); - - it("will pass boolean data as either an attribute or a property", function() { - this.weight = 3; - let data = wc.bool || wc.hasAttribute("bool"); - expect(data).to.be.true; - // Extra test to see if AngularJS just left its binding syntax on - // the attribute and didn't actually set anything :P - if (!wc.bool) { - data = wc.getAttribute("bool"); - expect(data.includes("{{")).to.be.false; - } - }); - - it("will pass numeric data as either an attribute or a property", function() { - this.weight = 3; - let data = wc.num || wc.getAttribute("num"); - expect(parseInt(data, 10)).to.eql(42); - }); - - it("will pass string data as either an attribute or a property", function() { - this.weight = 3; - let data = wc.str || wc.getAttribute("str"); - expect(data).to.eql("Angular"); - }); - }); - - describe("events", () => { - it("can imperatively listen to a DOM event dispatched by a Custom Element", function() { - this.weight = 3; - const root = compile("")(scope)[0]; - scope.$digest(); - let wc = root.querySelector("#wc"); - let handled = root.querySelector("#handled"); - expect(handled.textContent).to.eql("false"); - wc.click(); - scope.$digest(); - expect(handled.textContent).to.eql("true"); - }); - }); - -}); diff --git a/libraries/angularjs/src/components.js b/libraries/angularjs/src/components.js index f7f7a0f369..a45d0bd1a5 100644 --- a/libraries/angularjs/src/components.js +++ b/libraries/angularjs/src/components.js @@ -72,9 +72,9 @@ const ComponentWithProps = { angular.extend(this, { bool: true, num: 42, - str: 'Angular', - arr: ['A', 'n', 'g', 'u', 'l', 'a', 'r'], - obj: { org: 'angular', repo: 'angular' }, + str: 'custom', + arr: ['c', 'u', 's', 't', 'o', 'm'], + obj: { org: 'webcomponents', repo: 'custom-elements-everywhere' }, camelCaseObj: { label: "passed" } }); } diff --git a/libraries/angularjs/tests.webpack.js b/libraries/angularjs/tests.webpack.js index 7db7248ea2..70ceef43f1 100644 --- a/libraries/angularjs/tests.webpack.js +++ b/libraries/angularjs/tests.webpack.js @@ -17,7 +17,77 @@ import 'angular'; import 'angular-mocks'; +import prodApp from "./src/app.module"; -// Run basic and advanced tests through Karma -require('./src/basic-tests.js'); -require('./src/advanced-tests.js'); +import basicTests from "basic-tests"; +import advancedTests from "advanced-tests" + +describe('', function () { + beforeEach(angular.mock.module(prodApp)); + + let compile; + let scope; + let interval; + + beforeEach( + inject(($compile, $rootScope, $interval) => { + compile = $compile; + scope = $rootScope; + interval = $interval; + }) + ); + + function render(component) { + const root = compile(component)(scope)[0]; + scope.$apply(); + const wc = root.querySelector('#wc'); + return { wc, root } + } + + const renderers = { + renderComponentWithoutChildren() { + return render('') + }, + renderComponentWithChildren() { + return render('') + }, + renderComponentWithChildrenRerender() { + const result = render(''); + interval.flush(1000); + return result; + }, + renderComponentWithDifferentViews() { + scope.showWc = true; + const { wc, root } = render(''); + + function toggle() { + scope.showWc = !scope.showWc; + scope.$apply(); + } + + return { wc, toggle, root } + }, + renderComponentWithProperties() { + return render('') + }, + renderComponentWithImperativeEvent() { + const { wc, root } = render(''); + function click() { + wc.click(); + scope.$digest(); + } + return { wc, click, root }; + }, + renderComponentWithDeclarativeEvent() { + const { wc, root } = render(''); + function click() { + wc.click(); + scope.$digest(); + } + return { wc, click, root }; + } + }; + + basicTests(renderers); + advancedTests(renderers); +}); diff --git a/libraries/dio/karma.conf.js b/libraries/dio/karma.conf.js index e07eaa6a0c..4594b42165 100644 --- a/libraries/dio/karma.conf.js +++ b/libraries/dio/karma.conf.js @@ -61,6 +61,7 @@ module.exports = function(config) { resolve: { modules: [ path.resolve(__dirname, '../__shared__/webcomponents/src'), + path.resolve(__dirname, '../__shared__/tests/src'), path.resolve(__dirname, './node_modules'), path.resolve(__dirname, '../../node_modules'), ] diff --git a/libraries/dio/src/advanced-tests.js b/libraries/dio/src/advanced-tests.js deleted file mode 100644 index b8ed66cd9a..0000000000 --- a/libraries/dio/src/advanced-tests.js +++ /dev/null @@ -1,140 +0,0 @@ -/** - * @license - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { h, render } from "dio.js"; -import { expect } from "chai"; -import { - ComponentWithoutChildren, - ComponentWithChildren, - ComponentWithChildrenRerender, - ComponentWithDifferentViews, - ComponentWithProperties, - ComponentWithUnregistered, - ComponentWithImperativeEvent, - ComponentWithDeclarativeEvent -} from "./components"; - -// Setup the test harness. This will get cleaned out with every test. -let app = document.createElement("div"); -app.id = "app"; -document.body.appendChild(app); -let scratch; // This will hold the actual element under test. - -beforeEach(function() { - scratch = document.createElement("div"); - scratch.id = "scratch"; - app.appendChild(scratch); -}); - -afterEach(function() { - app.innerHTML = ""; - scratch = null; -}); - -describe("advanced support", function() { - - describe("attributes and properties", function() { - it("will pass array data as a property", function() { - this.weight = 2; - render(, scratch); - let wc = scratch.querySelector("#wc"); - let data = wc.arr; - expect(data).to.eql(["D", "I", "O"]); - }); - - it("will pass object data as a property", function() { - this.weight = 2; - render(, scratch); - let wc = scratch.querySelector("#wc"); - let data = wc.obj; - expect(data).to.eql({ org: "thysultan", repo: "dio.js" }); - }); - - it("will pass object data to a camelCase-named property", function() { - this.weight = 2; - render(, scratch); - let wc = scratch.querySelector("#wc"); - let data = wc.camelCaseObj; - expect(data).to.eql({ label: "passed" }); - }); - - }); - - describe("events", function() { - it("can declaratively listen to a lowercase DOM event dispatched by a Custom Element", function() { - this.weight = 2; - let component; - render( {component = instance}} />, scratch); - let wc = scratch.querySelector("#wc"); - expect(wc).to.exist; - let handled = scratch.querySelector("#lowercase"); - expect(handled.textContent).to.eql("false"); - wc.click(); - component.forceUpdate(); - expect(handled.textContent).to.eql("true"); - }); - - it("can declaratively listen to a kebab-case DOM event dispatched by a Custom Element", function() { - this.weight = 1; - let component; - render( {component = instance}} />, scratch); - let wc = scratch.querySelector("#wc"); - let handled = scratch.querySelector("#kebab"); - expect(handled.textContent).to.eql("false"); - wc.click(); - component.forceUpdate(); - expect(handled.textContent).to.eql("true"); - }); - - it("can declaratively listen to a camelCase DOM event dispatched by a Custom Element", function() { - this.weight = 1; - let component; - render( {component = instance}} />, scratch); - let wc = scratch.querySelector("#wc"); - let handled = scratch.querySelector("#camel"); - expect(handled.textContent).to.eql("false"); - wc.click(); - component.forceUpdate(); - expect(handled.textContent).to.eql("true"); - }); - - it("can declaratively listen to a CAPScase DOM event dispatched by a Custom Element", function() { - this.weight = 1; - let component; - render( {component = instance}} />, scratch); - let wc = scratch.querySelector("#wc"); - let handled = scratch.querySelector("#caps"); - expect(handled.textContent).to.eql("false"); - wc.click(); - component.forceUpdate(); - expect(handled.textContent).to.eql("true"); - }); - - it("can declaratively listen to a PascalCase DOM event dispatched by a Custom Element", function() { - this.weight = 1; - let component; - render( {component = instance}} />, scratch); - let wc = scratch.querySelector("#wc"); - let handled = scratch.querySelector("#pascal"); - expect(handled.textContent).to.eql("false"); - wc.click(); - component.forceUpdate(); - expect(handled.textContent).to.eql("true"); - }); - }); - -}); diff --git a/libraries/dio/src/basic-tests.js b/libraries/dio/src/basic-tests.js deleted file mode 100644 index 4c597a0e99..0000000000 --- a/libraries/dio/src/basic-tests.js +++ /dev/null @@ -1,148 +0,0 @@ -/** - * @license - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { h, render } from "dio.js"; -import { expect } from "chai"; -import { - ComponentWithoutChildren, - ComponentWithChildren, - ComponentWithChildrenRerender, - ComponentWithDifferentViews, - ComponentWithProperties, - ComponentWithUnregistered, - ComponentWithImperativeEvent, - ComponentWithDeclarativeEvent -} from "./components"; - -// Setup the test harness. This will get cleaned out with every test. -let app = document.createElement("div"); -app.id = "app"; -document.body.appendChild(app); -let scratch; // This will hold the actual element under test. - -beforeEach(function() { - scratch = document.createElement("div"); - scratch.id = "scratch"; - app.appendChild(scratch); -}); - -afterEach(function() { - app.innerHTML = ""; - scratch = null; -}); - -describe("basic support", function() { - - describe("no children", function() { - it("can display a Custom Element with no children", function() { - this.weight = 3; - render(, scratch), scratch; - let wc = scratch.querySelector("#wc"); - expect(wc).to.exist; - }); - }); - - describe("with children", function() { - function expectHasChildren(wc) { - expect(wc).to.exist; - let shadowRoot = wc.shadowRoot; - let heading = shadowRoot.querySelector("h1"); - expect(heading).to.exist; - expect(heading.textContent).to.eql("Test h1"); - let paragraph = shadowRoot.querySelector("p"); - expect(paragraph).to.exist; - expect(paragraph.textContent).to.eql("Test p"); - } - - it("can display a Custom Element with children in a Shadow Root", function() { - this.weight = 3; - render(, scratch) - let wc = scratch.querySelector("#wc"); - expectHasChildren(wc); - }); - - it("can display a Custom Element with children in a Shadow Root and pass in Light DOM children", async function() { - this.weight = 3; - let component; - render( {component = instance}} />, scratch) - let wc = scratch.querySelector("#wc"); - await Promise.resolve(); - component.forceUpdate(); - expectHasChildren(wc); - expect(wc.textContent.includes("2")).to.be.true; - }); - - it("can display a Custom Element with children in the Shadow DOM and handle hiding and showing the element", function() { - this.weight = 3; - let component; - render( {component = instance}} />, scratch); - let wc = scratch.querySelector("#wc"); - expectHasChildren(wc); - component.toggle(); - component.forceUpdate(); - let dummy = scratch.querySelector("#dummy"); - expect(dummy).to.exist; - expect(dummy.textContent).to.eql("Dummy view"); - component.toggle(); - component.forceUpdate(); - wc = scratch.querySelector("#wc"); - expectHasChildren(wc); - }); - }); - - describe("attributes and properties", function() { - it("will pass boolean data as either an attribute or a property", function() { - this.weight = 3; - render(, scratch); - let wc = scratch.querySelector("#wc"); - let data = wc.bool || wc.hasAttribute("bool"); - expect(data).to.be.true; - }); - - it("will pass numeric data as either an attribute or a property", function() { - this.weight = 3; - render(, scratch); - let wc = scratch.querySelector("#wc"); - let data = wc.num || wc.getAttribute("num"); - expect(parseInt(data, 10)).to.eql(42); - }); - - it("will pass string data as either an attribute or a property", function() { - this.weight = 3; - render(, scratch); - let wc = scratch.querySelector("#wc"); - let data = wc.str || wc.getAttribute("str"); - expect(data).to.eql("DIO"); - }); - }); - - describe("events", function() { - it("can imperatively listen to a DOM event dispatched by a Custom Element", function() { - this.weight = 3; - let component - render( {component = instance}} />, scratch); - let wc = scratch.querySelector("#wc"); - expect(wc).to.exist; - let handled = scratch.querySelector("#handled"); - expect(handled.textContent).to.eql("false"); - wc.click(); - component.forceUpdate(); - expect(handled.textContent).to.eql("true"); - }); - }); - -}); diff --git a/libraries/dio/src/components.js b/libraries/dio/src/components.js index 78df469ca7..e9d60e2b3a 100644 --- a/libraries/dio/src/components.js +++ b/libraries/dio/src/components.js @@ -89,9 +89,9 @@ export class ComponentWithProperties extends Component { const data = { bool: true, num: 42, - str: 'DIO', - arr: ['D', 'I', 'O'], - obj: { org: 'thysultan', repo: 'dio.js' }, + str: 'custom', + arr: ['c', 'u', 's', 't', 'o', 'm'], + obj: { org: 'webcomponents', repo: 'custom-elements-everywhere' }, camelCaseObj: { label: "passed" } }; return ( diff --git a/libraries/dio/tests.webpack.js b/libraries/dio/tests.webpack.js index a42a8d9a9d..cb392042eb 100644 --- a/libraries/dio/tests.webpack.js +++ b/libraries/dio/tests.webpack.js @@ -15,6 +15,86 @@ * limitations under the License. */ -// Run basic and advanced tests through Karma -require('./src/basic-tests.js'); -require('./src/advanced-tests.js'); +import {h, render} from "dio.js"; +import { + ComponentWithoutChildren, + ComponentWithChildren, + ComponentWithChildrenRerender, + ComponentWithDifferentViews, + ComponentWithProperties, + ComponentWithImperativeEvent, + ComponentWithDeclarativeEvent +} from "./src/components"; + +import basicTests from 'basic-tests'; +import advancedTests from 'advanced-tests'; + + +// Setup the test harness. This will get cleaned out with every test. +let app = document.createElement("div"); +app.id = "app"; +document.body.appendChild(app); +let scratch; // This will hold the actual element under test. + +beforeEach(function () { + scratch = document.createElement("div"); + scratch.id = "scratch"; + app.appendChild(scratch); +}); + +afterEach(function () { + app.innerHTML = ""; + scratch = null; +}); + +function _render(Component) { + let component + render( component = instance} />, scratch), scratch; + const wc = scratch.querySelector("#wc"); + return { wc, component } +} + +const renderers = { + renderComponentWithoutChildren() { + return _render(ComponentWithoutChildren); + }, + renderComponentWithChildren() { + return _render(ComponentWithChildren); + }, + async renderComponentWithChildrenRerender() { + const { wc, component } = _render(ComponentWithChildrenRerender); + await Promise.resolve(); + component.forceUpdate(); + return { wc } + }, + renderComponentWithDifferentViews() { + const { wc, component } = _render(ComponentWithDifferentViews); + function toggle() { + component.toggle(); + component.forceUpdate(); + } + return { wc, toggle } + }, + renderComponentWithProperties() { + return _render(ComponentWithProperties); + }, + renderComponentWithImperativeEvent() { + const { wc, component } = _render(ComponentWithImperativeEvent); + function click() { + wc.click(); + component.forceUpdate(); + } + return { wc, click }; + }, + renderComponentWithDeclarativeEvent() { + const { wc, component } = _render(ComponentWithDeclarativeEvent); + function click() { + wc.click(); + component.forceUpdate(); + } + return { wc, click }; + } +}; + +basicTests(renderers); +advancedTests(renderers); \ No newline at end of file diff --git a/libraries/react/karma.conf.js b/libraries/react/karma.conf.js index e1be84b4c3..abcbd123c3 100644 --- a/libraries/react/karma.conf.js +++ b/libraries/react/karma.conf.js @@ -61,6 +61,7 @@ module.exports = function(config) { resolve: { modules: [ path.resolve(__dirname, '../__shared__/webcomponents/src'), + path.resolve(__dirname, '../__shared__/tests/src'), path.resolve(__dirname, './node_modules'), path.resolve(__dirname, '../../node_modules'), ] diff --git a/libraries/react/src/advanced-tests.js b/libraries/react/src/advanced-tests.js deleted file mode 100644 index 3cf56cd669..0000000000 --- a/libraries/react/src/advanced-tests.js +++ /dev/null @@ -1,217 +0,0 @@ -/** - * @license - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import React from "react"; -import { createRoot } from "react-dom/client"; -import { act } from "react-dom/test-utils"; -import { expect } from "chai"; -import { - ComponentWithoutChildren, - ComponentWithChildren, - ComponentWithChildrenRerender, - ComponentWithDifferentViews, - ComponentWithProperties, - ComponentWithUnregistered, - ComponentWithImperativeEvent, - ComponentWithDeclarativeEvent -} from "./components"; - -// Setup the test harness. This will get cleaned out with every test. -let app = document.createElement("div"); -app.id = "app"; -document.body.appendChild(app); -let scratch; // This will hold the actual element under test. - -let reactRoot = null; -function render(element) { - act(() => { - reactRoot.render(element); - }); -} - -before(() => { - window.IS_REACT_ACT_ENVIRONMENT = true; -}) - -after(() => { - window.IS_REACT_ACT_ENVIRONMENT = false; -}) - -beforeEach(function() { - scratch = document.createElement("div"); - scratch.id = "scratch"; - app.appendChild(scratch); - - reactRoot = createRoot(scratch); -}); - -afterEach(function() { - app.innerHTML = ""; - scratch = null; - - act(() => { - reactRoot.unmount(); - }); -}); - -describe("advanced support", function() { - - describe("attributes and properties", function() { - it("will pass array data as a property", function() { - this.weight = 2; - let root; - render( - { - root = current; - }} - /> - ); - let wc = root.wc; - let data = wc.arr; - expect(data).to.eql(["R", "e", "a", "c", "t"]); - }); - - it("will pass object data as a property", function() { - this.weight = 2; - let root; - render( - { - root = current; - }} - /> - ); - let wc = root.wc; - let data = wc.obj; - expect(data).to.eql({ org: "facebook", repo: "react" }); - }); - - it("will pass object data to a camelCase-named property", function() { - this.weight = 2; - let root; - render( - { - root = current; - }} - /> - ); - let wc = root.wc; - let data = wc.camelCaseObj; - expect(data).to.eql({ label: "passed" }); - }); - }); - - describe("events", function() { - it("can declaratively listen to a lowercase DOM event dispatched by a Custom Element", function() { - this.weight = 2; - let root; - render( - { - root = current; - }} - /> - ); - let wc = root.wc; - let handled = root.lowercase; - expect(handled.textContent).to.eql("false"); - act(() => { - wc.click(); - }); - expect(handled.textContent).to.eql("true"); - }); - - it("can declaratively listen to a kebab-case DOM event dispatched by a Custom Element", function() { - this.weight = 1; - let root; - render( - { - root = current; - }} - /> - ); - let wc = root.wc; - let handled = root.kebab; - expect(handled.textContent).to.eql("false"); - act(() => { - wc.click(); - }); - expect(handled.textContent).to.eql("true"); - }); - - it("can declaratively listen to a camelCase DOM event dispatched by a Custom Element", function() { - this.weight = 1; - let root; - render( - { - root = current; - }} - /> - ); - let wc = root.wc; - let handled = root.camel; - expect(handled.textContent).to.eql("false"); - act(() => { - wc.click(); - }); - expect(handled.textContent).to.eql("true"); - }); - - it("can declaratively listen to a CAPScase DOM event dispatched by a Custom Element", function() { - this.weight = 1; - let root; - render( - { - root = current; - }} - /> - ); - let wc = root.wc; - let handled = root.caps; - expect(handled.textContent).to.eql("false"); - act(() => { - wc.click(); - }); - expect(handled.textContent).to.eql("true"); - }); - - it("can declaratively listen to a PascalCase DOM event dispatched by a Custom Element", function() { - this.weight = 1; - let root; - render( - { - root = current; - }} - /> - ); - let wc = root.wc; - let handled = root.pascal; - expect(handled.textContent).to.eql("false"); - act(() => { - wc.click(); - }); - expect(handled.textContent).to.eql("true"); - }); - }); - -}); diff --git a/libraries/react/src/basic-tests.js b/libraries/react/src/basic-tests.js deleted file mode 100644 index 3400a37e8b..0000000000 --- a/libraries/react/src/basic-tests.js +++ /dev/null @@ -1,258 +0,0 @@ -/** - * @license - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import React from "react"; -import { createRoot } from "react-dom/client"; -import { act } from "react-dom/test-utils"; -import * as ReactDOM from "react-dom"; -import { expect } from "chai"; -import { - ComponentWithoutChildren, - ComponentWithChildren, - ComponentWithChildrenRerender, - ComponentWithDifferentViews, - ComponentWithProperties, - ComponentWithUnregistered, - ComponentWithImperativeEvent, - ComponentWithDeclarativeEvent, -} from "./components"; - -// Setup the test harness. This will get cleaned out with every test. -let app = document.createElement("div"); -app.id = "app"; -document.body.appendChild(app); -let scratch; // This will hold the actual element under test. - -let reactRoot = null; -function render(element) { - act(() => { - reactRoot.render(element); - }); -} - -before(() => { - window.IS_REACT_ACT_ENVIRONMENT = true; -}); - -beforeEach(function () { - scratch = document.createElement("div"); - scratch.id = "scratch"; - app.appendChild(scratch); - - reactRoot = createRoot(scratch); -}); - -afterEach(function () { - app.innerHTML = ""; - scratch = null; - - act(() => { - reactRoot.unmount(); - }); -}); - -describe("basic support", function () { - describe("no children", function () { - it("can display a Custom Element with no children", function () { - this.weight = 3; - let root; - render( - { - root = current; - }} - /> - ); - let wc = root.wc; - expect(wc).to.exist; - }); - }); - - describe("with children", function () { - function expectHasChildren(wc) { - expect(wc).to.exist; - let shadowRoot = wc.shadowRoot; - let heading = shadowRoot.querySelector("h1"); - expect(heading).to.exist; - expect(heading.textContent).to.eql("Test h1"); - let paragraph = shadowRoot.querySelector("p"); - expect(paragraph).to.exist; - expect(paragraph.textContent).to.eql("Test p"); - } - - it("can display a Custom Element with children in a Shadow Root", function () { - this.weight = 3; - let root; - render( - { - root = current; - }} - /> - ); - let wc = root.wc; - expectHasChildren(wc); - }); - - it("can display a Custom Element with children in a Shadow Root and pass in Light DOM children", async function () { - this.weight = 3; - let root; - render( - { - root = current; - }} - /> - ); - let wc = root.wc; - await act(async () => { - await Promise.resolve(); - }); - expectHasChildren(wc); - expect(wc.textContent.includes("2")).to.be.true; - }); - - it("can display a Custom Element with children in the Shadow DOM and handle hiding and showing the element", function () { - this.weight = 3; - let root; - render( - { - root = current; - }} - /> - ); - let wc = root.wc; - expectHasChildren(wc); - act(() => { - root.toggle(); - }); - let dummy = root.dummy.current; - expect(dummy).to.exist; - expect(dummy.textContent).to.eql("Dummy view"); - act(() => { - root.toggle(); - }); - wc = root.wc; - expectHasChildren(wc); - }); - }); - - describe("attributes and properties", function () { - it("will pass boolean data as either an attribute or a property", function () { - this.weight = 3; - let root; - render( - { - root = current; - }} - /> - ); - let wc = root.wc; - let data = wc.bool || wc.hasAttribute("bool"); - expect(data).to.be.true; - }); - - it("will pass numeric data as either an attribute or a property", function () { - this.weight = 3; - let root; - render( - { - root = current; - }} - /> - ); - let wc = root.wc; - let data = wc.num || wc.getAttribute("num"); - expect(parseInt(data, 10)).to.eql(42); - }); - - it("will pass string data as either an attribute or a property", function () { - this.weight = 3; - let root; - render( - { - root = current; - }} - /> - ); - let wc = root.wc; - let data = wc.str || wc.getAttribute("str"); - expect(data).to.eql("React"); - }); - - // TODO: Is it the framework's responsibility to check if the underlying - // property is defined? Or should it just always assume it is and do its - // usual default behavior? Preact will actually check if it's defined and - // use an attribute if it is not, otherwise it prefers properties for - // everything. Is there a "right" answer in this situation? - - // it('will set boolean attributes on a Custom Element that has not already been defined and upgraded', function() { - // let root = ReactDOM.render(, scratch); - // let wc = ReactDOM.findDOMNode(root.refs.wc); - // expect(wc.hasAttribute('bool')).to.be.true; - // }); - - // it('will set numeric attributes on a Custom Element that has not already been defined and upgraded', function() { - // let root = ReactDOM.render(, scratch); - // let wc = ReactDOM.findDOMNode(root.refs.wc); - // expect(wc.getAttribute('num')).to.eql('42'); - // }); - - // it('will set string attributes on a Custom Element that has not already been defined and upgraded', function() { - // let root = ReactDOM.render(, scratch); - // let wc = ReactDOM.findDOMNode(root.refs.wc); - // expect(wc.getAttribute('str')).to.eql('React'); - // }); - - // it('will set array attributes on a Custom Element that has not already been defined and upgraded', function() { - // let root = ReactDOM.render(, scratch); - // let wc = ReactDOM.findDOMNode(root.refs.wc); - // expect(wc.getAttribute('arr')).to.eql(JSON.stringify(['R', 'e', 'a', 'c', 't'])); - // }); - - // it('will set object attributes on a Custom Element that has not already been defined and upgraded', function() { - // let root = ReactDOM.render(, scratch); - // let wc = ReactDOM.findDOMNode(root.refs.wc); - // expect(wc.getAttribute('obj')).to.eql(JSON.stringify({ org: 'facebook', repo: 'react' })); - // }); - }); - - describe("events", function () { - it("can imperatively listen to a DOM event dispatched by a Custom Element", function () { - this.weight = 3; - let root; - render( - { - root = current; - }} - /> - ); - let wc = root.wc; - let handled = root.handled; - expect(handled.textContent).to.eql("false"); - act(() => { - wc.click(); - }); - expect(handled.textContent).to.eql("true"); - }); - }); -}); diff --git a/libraries/react/src/components.js b/libraries/react/src/components.js index 20a7f82c23..63b721ee6c 100644 --- a/libraries/react/src/components.js +++ b/libraries/react/src/components.js @@ -78,7 +78,7 @@ export class ComponentWithDifferentViews extends Component { {showWC ? ( this.wc = el}> ) : ( -
Dummy view
+
Dummy view
)} ); @@ -90,9 +90,9 @@ export class ComponentWithProperties extends Component { const data = { bool: true, num: 42, - str: 'React', - arr: ['R', 'e', 'a', 'c', 't'], - obj: { org: 'facebook', repo: 'react' }, + str: 'custom', + arr: ['c', 'u', 's', 't', 'o', 'm'], + obj: { org: 'webcomponents', repo: 'custom-elements-everywhere' }, camelCaseObj: { label: "passed" } }; return ( @@ -153,7 +153,7 @@ export class ComponentWithImperativeEvent extends Component { let state = this.state; return (
-
this.handled = el}>{state.eventHandled.toString()}
+
this.handled = el}>{state.eventHandled.toString()}
this.wc = el}>
); @@ -195,11 +195,11 @@ export class ComponentWithDeclarativeEvent extends Component { let state = this.state; return (
-
this.lowercase = el}>{state.lowercaseHandled.toString()}
-
this.kebab = el}>{state.kebabHandled.toString()}
-
this.camel = el}>{state.camelHandled.toString()}
-
this.caps = el}>{state.capsHandled.toString()}
-
this.pascal = el}>{state.pascalHandled.toString()}
+
this.lowercase = el}>{state.lowercaseHandled.toString()}
+
this.kebab = el}>{state.kebabHandled.toString()}
+
this.camel = el}>{state.camelHandled.toString()}
+
this.caps = el}>{state.capsHandled.toString()}
+
this.pascal = el}>{state.pascalHandled.toString()}
this.wc = el} onlowercaseevent={this.handleLowercaseEvent} onkebab-event={this.handleKebabEvent} diff --git a/libraries/react/tests.webpack.js b/libraries/react/tests.webpack.js index a42a8d9a9d..89b02fda0f 100644 --- a/libraries/react/tests.webpack.js +++ b/libraries/react/tests.webpack.js @@ -15,6 +15,110 @@ * limitations under the License. */ -// Run basic and advanced tests through Karma -require('./src/basic-tests.js'); -require('./src/advanced-tests.js'); +import React from "react"; +import {createRoot} from "react-dom/client"; +import {act} from "react-dom/test-utils"; +import { + ComponentWithoutChildren, + ComponentWithChildren, + ComponentWithChildrenRerender, + ComponentWithDifferentViews, + ComponentWithProperties, + ComponentWithImperativeEvent, + ComponentWithDeclarativeEvent, +} from "./src/components"; + +import basicTests from 'basic-tests'; +import advancedTests from 'advanced-tests'; + +// Setup the test harness. This will get cleaned out with every test. +let app = document.createElement("div"); +app.id = "app"; +document.body.appendChild(app); +let scratch; // This will hold the actual element under test. + +let reactRoot = null; + +before(() => { + window.IS_REACT_ACT_ENVIRONMENT = true; +}); + +beforeEach(function () { + scratch = document.createElement("div"); + scratch.id = "scratch"; + app.appendChild(scratch); + + reactRoot = createRoot(scratch); +}); + +afterEach(function () { + app.innerHTML = ""; + scratch = null; + + act(() => { + reactRoot.unmount(); + }); +}); + +function render(Component) { + let root; + act(() => { + reactRoot.render( + { + root = current; + }} + /> + ); + }); + return {wc: root.wc, root} +} + +const renderers = { + renderComponentWithoutChildren() { + return render(ComponentWithoutChildren); + }, + renderComponentWithChildren() { + return render(ComponentWithChildren); + }, + async renderComponentWithChildrenRerender() { + const results = render(ComponentWithChildrenRerender); + await act(async () => { + await Promise.resolve(); + }); + return results; + }, + renderComponentWithProperties() { + return render(ComponentWithProperties); + }, + renderComponentWithDifferentViews() { + const { wc, root } = render(ComponentWithDifferentViews); + function toggle() { + act(() => { + root.toggle(); + }); + } + return { wc, toggle } + }, + renderComponentWithImperativeEvent() { + const { wc, root } = render(ComponentWithImperativeEvent) + function click() { + act(() => { + wc.click(); + }); + } + return { wc, click } + }, + renderComponentWithDeclarativeEvent() { + const { wc } = render(ComponentWithDeclarativeEvent) + function click() { + act(() => { + wc.click(); + }); + } + return { wc, click } + } +} + +basicTests(renderers); +advancedTests(renderers); diff --git a/libraries/riot/karma.conf.js b/libraries/riot/karma.conf.js index 1532866e7c..b4f209e301 100644 --- a/libraries/riot/karma.conf.js +++ b/libraries/riot/karma.conf.js @@ -61,6 +61,7 @@ module.exports = function(config) { resolve: { modules: [ path.resolve(__dirname, '../__shared__/webcomponents/src'), + path.resolve(__dirname, '../__shared__/tests/src'), path.resolve(__dirname, './node_modules'), path.resolve(__dirname, '../../node_modules'), ] diff --git a/libraries/riot/src/advanced-tests.js b/libraries/riot/src/advanced-tests.js deleted file mode 100644 index 0c34a6b8c0..0000000000 --- a/libraries/riot/src/advanced-tests.js +++ /dev/null @@ -1,124 +0,0 @@ -/** - * @license - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { expect } from 'chai' -import { component } from 'riot' -import { - ComponentWithProperties, - ComponentWithDeclarativeEvent -} from './components' - -// Setup the test harness. This will get cleaned out with every test. -let app = document.createElement('div') -app.id = 'app' -document.body.appendChild(app) -let scratch // This will hold the actual element under test. - -beforeEach(function() { - scratch = document.createElement('div') - scratch.id = 'scratch' - app.appendChild(scratch) -}) - -afterEach(function() { - app.innerHTML = '' - scratch = null -}) - -describe('advanced support', function() { - - describe('attributes and properties', function() { - it('will pass array data as a property', function() { - this.weight = 2 - component(ComponentWithProperties)(scratch) - let wc = scratch.querySelector('#wc') - let data = wc.arr - expect(data).to.eql(['r', 'i', 'o', 't']) - }) - - it('will pass object data as a property', function() { - this.weight = 2 - component(ComponentWithProperties)(scratch) - let wc = scratch.querySelector('#wc') - let data = wc.obj - expect(data).to.eql({ org: 'riotjs', repo: 'riot' }) - }) - - it('will pass object data to a camelCase-named property', function() { - this.weight = 2 - component(ComponentWithProperties)(scratch) - let wc = scratch.querySelector('#wc') - let data = wc.camelCaseObj; - expect(data).to.eql({ label: "passed" }); - }) - - }) - - describe('events', function() { - it('can declaratively listen to a lowercase DOM event dispatched by a Custom Element', function() { - this.weight = 2 - component(ComponentWithDeclarativeEvent)(scratch) - let wc = scratch.querySelector('#wc') - expect(wc).to.exist - let handled = scratch.querySelector('#lowercase') - expect(handled.textContent).to.eql('false') - wc.click() - expect(handled.textContent).to.eql('true') - }) - - it('can declaratively listen to a kebab-case DOM event dispatched by a Custom Element', function() { - this.weight = 1 - component(ComponentWithDeclarativeEvent)(scratch) - let wc = scratch.querySelector('#wc') - let handled = scratch.querySelector('#kebab') - expect(handled.textContent).to.eql('false') - wc.click() - expect(handled.textContent).to.eql('true') - }) - - it('can declaratively listen to a camelCase DOM event dispatched by a Custom Element', function() { - this.weight = 1 - component(ComponentWithDeclarativeEvent)(scratch) - let wc = scratch.querySelector('#wc') - let handled = scratch.querySelector('#camel') - expect(handled.textContent).to.eql('false') - wc.click() - expect(handled.textContent).to.eql('true') - }) - - it('can declaratively listen to a CAPScase DOM event dispatched by a Custom Element', function() { - this.weight = 1 - component(ComponentWithDeclarativeEvent)(scratch) - let wc = scratch.querySelector('#wc') - let handled = scratch.querySelector('#caps') - expect(handled.textContent).to.eql('false') - wc.click() - expect(handled.textContent).to.eql('true') - }) - - it('can declaratively listen to a PascalCase DOM event dispatched by a Custom Element', function() { - this.weight = 1 - component(ComponentWithDeclarativeEvent)(scratch) - let wc = scratch.querySelector('#wc') - let handled = scratch.querySelector('#pascal') - expect(handled.textContent).to.eql('false') - wc.click() - expect(handled.textContent).to.eql('true') - }) - }) - -}) diff --git a/libraries/riot/src/basic-tests.js b/libraries/riot/src/basic-tests.js deleted file mode 100644 index 83298d2284..0000000000 --- a/libraries/riot/src/basic-tests.js +++ /dev/null @@ -1,173 +0,0 @@ -/** - * @license - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { expect } from 'chai' -import { component } from 'riot' -import { - ComponentWithoutChildren, - ComponentWithChildren, - ComponentWithChildrenRerender, - ComponentWithDifferentViews, - ComponentWithProperties, - ComponentWithUnregistered, - ComponentWithImperativeEvent -} from './components' - -// Setup the test harness. This will get cleaned out with every test. -let app = document.createElement('div') -app.id = 'app' -document.body.appendChild(app) -let scratch // This will hold the actual element under test. - -beforeEach(function() { - scratch = document.createElement('div') - scratch.id = 'scratch' - app.appendChild(scratch) -}) - -afterEach(function() { - app.innerHTML = '' - scratch = null -}) - -describe('basic support', function() { - - describe('no children', function() { - it('can display a Custom Element with no children', function() { - this.weight = 3 - component(ComponentWithoutChildren)(scratch) - let wc = scratch.querySelector('#wc') - expect(wc).to.exist - }) - }) - - describe('with children', function() { - function expectHasChildren(wc) { - expect(wc).to.exist - let shadowRoot = wc.shadowRoot - let heading = shadowRoot.querySelector('h1') - expect(heading).to.exist - expect(heading.textContent).to.eql('Test h1') - let paragraph = shadowRoot.querySelector('p') - expect(paragraph).to.exist - expect(paragraph.textContent).to.eql('Test p') - } - - it('can display a Custom Element with children in a Shadow Root', function() { - this.weight = 3 - component(ComponentWithChildren)(scratch) - let wc = scratch.querySelector('#wc') - expectHasChildren(wc) - }) - - it('can display a Custom Element with children in a Shadow Root and pass in Light DOM children', function() { - this.weight = 3 - component(ComponentWithChildrenRerender)(scratch) - let wc = scratch.querySelector('#wc') - expectHasChildren(wc) - expect(wc.textContent.includes('2')).to.be.true - }) - - it('can display a Custom Element with children in the Shadow DOM and handle hiding and showing the element', function() { - this.weight = 3 - const el = component(ComponentWithDifferentViews)(scratch) - let wc = scratch.querySelector('#wc') - expectHasChildren(wc) - el.toggle() - let dummy = scratch.querySelector('#dummy') - expect(dummy).to.exist - expect(dummy.textContent).to.eql('Dummy view') - el.toggle() - wc = scratch.querySelector('#wc') - expectHasChildren(wc) - }) - }) - - describe('attributes and properties', function() { - it('will pass boolean data as either an attribute or a property', function() { - this.weight = 3 - component(ComponentWithProperties)(scratch) - let wc = scratch.querySelector('#wc') - let data = wc.bool || wc.hasAttribute('bool') - expect(data).to.be.true - }) - - it('will pass numeric data as either an attribute or a property', function() { - this.weight = 3 - component(ComponentWithProperties)(scratch) - let wc = scratch.querySelector('#wc') - let data = wc.num || wc.getAttribute('num') - expect(parseInt(data, 10)).to.eql(42) - }) - - it('will pass string data as either an attribute or a property', function() { - this.weight = 3 - component(ComponentWithProperties)(scratch) - let wc = scratch.querySelector('#wc') - let data = wc.str || wc.getAttribute('str') - expect(data).to.eql('riot') - }) - - // Riot.js passes all the following tests but they must be commented out - // being consistent with the other frameworks ¯\_(ツ)_/¯ - /* - it('will set boolean attributes on a Custom Element that has not already been defined and upgraded', function() { - component(ComponentWithUnregistered)(scratch) - let wc = scratch.querySelector('#wc') - expect(wc.hasAttribute('bool')).to.be.true - }) - - it('will set numeric attributes on a Custom Element that has not already been defined and upgraded', function() { - component(ComponentWithUnregistered)(scratch) - let wc = scratch.querySelector('#wc') - expect(wc.getAttribute('num')).to.eql('42') - }) - - it('will set string attributes on a Custom Element that has not already been defined and upgraded', function() { - component(ComponentWithUnregistered)(scratch) - let wc = scratch.querySelector('#wc') - expect(wc.getAttribute('str')).to.eql('riot') - }) - - it('will set array properties on a Custom Element that has not already been defined and upgraded', function() { - component(ComponentWithUnregistered)(scratch) - let wc = scratch.querySelector('#wc') - expect(wc.arr).to.eql(['r', 'i', 'o', 't']) - }) - - it('will set object properties on a Custom Element that has not already been defined and upgraded', function() { - component(ComponentWithUnregistered)(scratch) - let wc = scratch.querySelector('#wc') - expect(wc.obj).to.eql({ org: 'riotjs', repo: 'riot' }) - }) - */ - }) - - describe('events', function() { - it('can imperatively listen to a DOM event dispatched by a Custom Element', function() { - this.weight = 3 - component(ComponentWithImperativeEvent)(scratch) - let wc = scratch.querySelector('#wc') - expect(wc).to.exist - let handled = scratch.querySelector('#handled') - expect(handled.textContent).to.eql('false') - wc.click() - expect(handled.textContent).to.eql('true') - }) - }) - -}) diff --git a/libraries/riot/src/components/ComponentWithProperties.riot b/libraries/riot/src/components/ComponentWithProperties.riot index dd975be44b..e102d76c99 100644 --- a/libraries/riot/src/components/ComponentWithProperties.riot +++ b/libraries/riot/src/components/ComponentWithProperties.riot @@ -5,9 +5,9 @@ state: { bool: true, num: 42, - str: 'riot', - arr: ['r', 'i', 'o', 't'], - obj: { org: 'riotjs', repo: 'riot' }, + str: 'custom', + arr: ['c', 'u', 's', 't', 'o', 'm'], + obj: { org: 'webcomponents', repo: 'custom-elements-everywhere' }, camelCaseObj: { label: "passed" }, } } diff --git a/libraries/riot/tests.webpack.js b/libraries/riot/tests.webpack.js index cf620e9bd9..d1bacdc985 100644 --- a/libraries/riot/tests.webpack.js +++ b/libraries/riot/tests.webpack.js @@ -15,6 +15,66 @@ * limitations under the License. */ -// Run basic and advanced tests through Karma -require('./src/basic-tests.js') -require('./src/advanced-tests.js') +import { component } from 'riot' +import { + ComponentWithoutChildren, + ComponentWithChildren, + ComponentWithChildrenRerender, + ComponentWithDifferentViews, + ComponentWithProperties, + ComponentWithImperativeEvent, + ComponentWithDeclarativeEvent +} from './src/components' + +import basicTests from 'basic-tests'; +import advancedTests from 'advanced-tests'; + +// Setup the test harness. This will get cleaned out with every test. +let app = document.createElement('div') +app.id = 'app' +document.body.appendChild(app) +let scratch // This will hold the actual element under test. + +beforeEach(function() { + scratch = document.createElement('div') + scratch.id = 'scratch' + app.appendChild(scratch) +}) + +afterEach(function() { + app.innerHTML = '' + scratch = null +}) + +function render(Component) { + const el = component(Component)(scratch) + return {wc: scratch.querySelector('#wc'), el} +} + +const renderers = { + renderComponentWithoutChildren() { + return render(ComponentWithoutChildren) + }, + renderComponentWithChildren() { + return render(ComponentWithChildren) + }, + renderComponentWithChildrenRerender() { + return render(ComponentWithChildrenRerender) + }, + renderComponentWithDifferentViews() { + const {wc, el} = render(ComponentWithDifferentViews) + return {wc, el, toggle: () => el.toggle()} + }, + renderComponentWithProperties() { + return render(ComponentWithProperties) + }, + renderComponentWithImperativeEvent() { + return render(ComponentWithImperativeEvent) + }, + renderComponentWithDeclarativeEvent() { + return render(ComponentWithDeclarativeEvent) + } +} + +basicTests(renderers); +advancedTests(renderers); \ No newline at end of file diff --git a/libraries/vue/karma.conf.js b/libraries/vue/karma.conf.js index 7980a53bae..01731633de 100644 --- a/libraries/vue/karma.conf.js +++ b/libraries/vue/karma.conf.js @@ -61,6 +61,7 @@ module.exports = function(config) { resolve: { modules: [ path.resolve(__dirname, '../__shared__/webcomponents/src'), + path.resolve(__dirname, '../__shared__/tests/src'), path.resolve(__dirname, './node_modules'), path.resolve(__dirname, '../../node_modules'), ], diff --git a/libraries/vue/src/advanced-tests.js b/libraries/vue/src/advanced-tests.js deleted file mode 100644 index d0f0b7c4f5..0000000000 --- a/libraries/vue/src/advanced-tests.js +++ /dev/null @@ -1,153 +0,0 @@ -/** - * @license - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {createApp, nextTick} from 'vue'; -import { - ComponentWithoutChildren, - ComponentWithChildren, - ComponentWithChildrenRerender, - ComponentWithDifferentViews, - ComponentWithProperties, - ComponentWithUnregistered, - ComponentWithImperativeEvent, - ComponentWithDeclarativeEvent -} from "./components"; -import { expect } from "chai"; - -const isCustomElement = (tagName) => { - return window.customElements.get(tagName) !== undefined; -} - -// Setup the test harness. This will get cleaned out with every test. -const container = document.createElement("div"); -document.body.appendChild(container); -let scratch; // This will hold the actual element under test. - -beforeEach(function() { - scratch = document.createElement("div"); - scratch.id = "scratch"; - container.appendChild(scratch); -}); - -afterEach(function() { - container.innerHTML = ""; - scratch = null; -}); - -describe("advanced support", function() { - - describe("attributes and properties", function() { - it("will pass array data as a property", function() { - this.weight = 2; - const app = createApp(ComponentWithProperties) - app.config.compilerOptions.isCustomElement = isCustomElement; - app.mount(scratch); - const wc = scratch.querySelector("#wc"); - const data = wc.arr; - expect(data).to.eql(["V", "u", "e"]); - }); - - it("will pass object data as a property", function() { - this.weight = 2; - const app = createApp(ComponentWithProperties) - app.config.compilerOptions.isCustomElement = isCustomElement; - app.mount(scratch); - const wc = scratch.querySelector("#wc"); - const data = wc.obj; - expect(data).to.eql({ org: "vuejs", repo: "vue" }); - }); - - it("will pass object data to a camelCase-named property", function() { - this.weight = 2; - const app = createApp(ComponentWithProperties) - app.config.compilerOptions.isCustomElement = isCustomElement; - app.mount(scratch); - const wc = scratch.querySelector("#wc"); - const data = wc.camelCaseObj; - expect(data).to.eql({ label: "passed" }); - }); - - }); - - describe("events", function() { - it("can declaratively listen to a lowercase DOM event dispatched by a Custom Element", async function() { - this.weight = 2; - const app = createApp(ComponentWithDeclarativeEvent) - app.config.compilerOptions.isCustomElement = isCustomElement; - app.mount(scratch); - const wc = scratch.querySelector("#wc"); - const handled = scratch.querySelector("#lowercase"); - expect(handled.textContent).to.eql("false"); - wc.click(); - await nextTick(); - expect(handled.textContent).to.eql("true"); - }); - - it("can declaratively listen to a kebab-case DOM event dispatched by a Custom Element", async function() { - this.weight = 1; - const app = createApp(ComponentWithDeclarativeEvent) - app.config.compilerOptions.isCustomElement = isCustomElement; - app.mount(scratch); - const wc = scratch.querySelector("#wc"); - const handled = scratch.querySelector("#kebab"); - expect(handled.textContent).to.eql("false"); - wc.click(); - await nextTick(); - expect(handled.textContent).to.eql("true"); - }); - - it("can declaratively listen to a camelCase DOM event dispatched by a Custom Element", async function() { - this.weight = 1; - const app = createApp(ComponentWithDeclarativeEvent) - app.config.compilerOptions.isCustomElement = isCustomElement; - app.mount(scratch); - const wc = scratch.querySelector("#wc"); - const handled = scratch.querySelector("#camel"); - expect(handled.textContent).to.eql("false"); - wc.click(); - await nextTick(); - expect(handled.textContent).to.eql("true"); - }); - - it("can declaratively listen to a CAPScase DOM event dispatched by a Custom Element", async function() { - this.weight = 1; - const app = createApp(ComponentWithDeclarativeEvent) - app.config.compilerOptions.isCustomElement = isCustomElement; - app.mount(scratch); - const wc = scratch.querySelector("#wc"); - const handled = scratch.querySelector("#caps"); - expect(handled.textContent).to.eql("false"); - wc.click(); - await nextTick(); - expect(handled.textContent).to.eql("true"); - }); - - it("can declaratively listen to a PascalCase DOM event dispatched by a Custom Element", async function() { - this.weight = 1; - const app = createApp(ComponentWithDeclarativeEvent) - app.config.compilerOptions.isCustomElement = isCustomElement; - app.mount(scratch); - const wc = scratch.querySelector("#wc"); - const handled = scratch.querySelector("#pascal"); - expect(handled.textContent).to.eql("false"); - wc.click(); - await nextTick(); - expect(handled.textContent).to.eql("true"); - }); - }); - -}); diff --git a/libraries/vue/src/basic-tests.js b/libraries/vue/src/basic-tests.js deleted file mode 100644 index 4e3a33bcf2..0000000000 --- a/libraries/vue/src/basic-tests.js +++ /dev/null @@ -1,196 +0,0 @@ -/** - * @license - * Copyright 2017 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {createApp, nextTick} from 'vue'; -import { - ComponentWithoutChildren, - ComponentWithChildren, - ComponentWithChildrenRerender, - ComponentWithDifferentViews, - ComponentWithProperties, - ComponentWithUnregistered, - ComponentWithImperativeEvent, - ComponentWithDeclarativeEvent -} from "./components"; -import { expect } from "chai"; - -// Setup the test harness. This will get cleaned out with every test. -const container = document.createElement("div"); -document.body.appendChild(container); -let scratch; // This will hold the actual element under test. - -const isCustomElement = (tagName) => { - return window.customElements.get(tagName) !== undefined; -} - -beforeEach(function() { - scratch = document.createElement("div"); - scratch.id = "scratch"; - container.appendChild(scratch); -}); - -afterEach(function() { - container.innerHTML = ""; - scratch = null; -}); - -describe("basic support", function() { - - describe("no children", function() { - it("can display a Custom Element with no children", function() { - this.weight = 3; - const app = createApp(ComponentWithoutChildren) - app.config.compilerOptions.isCustomElement = isCustomElement; - app.mount(scratch); - const wc = scratch.querySelector("#wc"); - expect(wc).to.exist; - }); - }); - - describe("with children", function() { - function expectHasChildren(wc) { - expect(wc).to.exist; - const shadowRoot = wc.shadowRoot; - const heading = shadowRoot.querySelector("h1"); - expect(heading).to.exist; - expect(heading.textContent).to.eql("Test h1"); - const paragraph = shadowRoot.querySelector("p"); - expect(paragraph).to.exist; - expect(paragraph.textContent).to.eql("Test p"); - } - - it("can display a Custom Element with children in a Shadow Root", function() { - this.weight = 3; - const app = createApp(ComponentWithChildren) - app.config.compilerOptions.isCustomElement = isCustomElement; - app.mount(scratch); - const wc = scratch.querySelector("#wc"); - expectHasChildren(wc); - }); - - it("can display a Custom Element with children in a Shadow Root and pass in Light DOM children", async function() { - this.weight = 3; - const app = createApp(ComponentWithChildrenRerender) - app.config.compilerOptions.isCustomElement = isCustomElement; - app.mount(scratch); - const wc = scratch.querySelector("#wc"); - // Waits for the tick in ComponentWithChildrenRerender's mount function - await nextTick(); - // Waits for the increment inside that tick to appear in the DOM. - await nextTick(); - expectHasChildren(wc); - expect(wc.textContent.includes("2")).to.be.true; - }); - - it("can display a Custom Element with children in the Shadow DOM and handle hiding and showing the element", async function() { - this.weight = 3; - const app = createApp(ComponentWithDifferentViews) - app.config.compilerOptions.isCustomElement = isCustomElement; - app.mount(scratch); - const toggler = scratch.querySelector('#toggler'); - let wc = scratch.querySelector("#wc"); - expectHasChildren(wc); - toggler.click(); - await nextTick(); - const dummy = scratch.querySelector("#dummy"); - expect(dummy).to.exist; - expect(dummy.textContent).to.eql("Dummy view"); - toggler.click(); - await nextTick(); - wc = scratch.querySelector("#wc"); - expectHasChildren(wc); - }); - }); - - describe("attributes and properties", function() { - it("will pass boolean data as either an attribute or a property", function() { - this.weight = 3; - const app = createApp(ComponentWithProperties) - app.config.compilerOptions.isCustomElement = isCustomElement; - app.mount(scratch); - const wc = scratch.querySelector("#wc"); - const data = wc.bool || wc.hasAttribute("bool"); - expect(data).to.be.true; - }); - - it("will pass numeric data as either an attribute or a property", function() { - this.weight = 3; - const app = createApp(ComponentWithProperties) - app.config.compilerOptions.isCustomElement = isCustomElement; - app.mount(scratch); - const wc = scratch.querySelector("#wc"); - const data = wc.num || wc.getAttribute("num"); - expect(parseInt(data, 10)).to.eql(42); - }); - - it("will pass string data as either an attribute or a property", function() { - this.weight = 3; - const app = createApp(ComponentWithProperties) - app.config.compilerOptions.isCustomElement = isCustomElement; - app.mount(scratch); - const wc = scratch.querySelector("#wc"); - const data = wc.str || wc.getAttribute("str"); - expect(data).to.eql("Vue"); - }); - - // it('will set boolean attributes on a Custom Element that has not already been defined and upgraded', function() { - // let root = new ComponentWithUnregistered().$mount(scratch).$el; - // let wc = root.querySelector('#wc'); - // expect(wc.hasAttribute('bool')).to.be.true; - // }); - - // it('will set numeric attributes on a Custom Element that has not already been defined and upgraded', function() { - // let root = new ComponentWithUnregistered().$mount(scratch).$el; - // let wc = root.querySelector('#wc'); - // expect(wc.getAttribute('num')).to.eql('42'); - // }); - - // it('will set string attributes on a Custom Element that has not already been defined and upgraded', function() { - // let root = new ComponentWithUnregistered().$mount(scratch).$el; - // let wc = root.querySelector('#wc'); - // expect(wc.getAttribute('str')).to.eql('Vue'); - // }); - - // it('will set array properties on a Custom Element that has not already been defined and upgraded', function() { - // let root = new ComponentWithUnregistered().$mount(scratch).$el; - // let wc = root.querySelector('#wc'); - // expect(wc.arr).to.eql(['V', 'u', 'e']); - // }); - - // it('will set object properties on a Custom Element that has not already been defined and upgraded', function() { - // let root = new ComponentWithUnregistered().$mount(scratch).$el; - // let wc = root.querySelector('#wc'); - // expect(wc.obj).to.eql({ org: 'vuejs', repo: 'vue' }); - // }); - }); - - describe("events", function() { - it("can imperatively listen to a DOM event dispatched by a Custom Element", async function() { - this.weight = 3; - const app = createApp(ComponentWithImperativeEvent) - app.config.compilerOptions.isCustomElement = isCustomElement; - app.mount(scratch); - const wc = scratch.querySelector("#wc"); - const handled = scratch.querySelector("#handled"); - expect(handled.textContent).to.eql("false"); - wc.click(); - await nextTick(); - expect(handled.textContent).to.eql("true"); - }); - }); - -}); diff --git a/libraries/vue/src/components.js b/libraries/vue/src/components.js index 9a4ac360b8..64f2cf6c66 100644 --- a/libraries/vue/src/components.js +++ b/libraries/vue/src/components.js @@ -92,9 +92,9 @@ export const ComponentWithProperties = defineComponent({ return { bool: true, num: 42, - str: 'Vue', - arr: ['V', 'u', 'e'], - obj: { org: 'vuejs', repo: 'vue' }, + str: 'custom', + arr: ['c', 'u', 's', 't', 'o', 'm'], + obj: { org: 'webcomponents', repo: 'custom-elements-everywhere' }, camelCaseObj: { label: "passed" } } } diff --git a/libraries/vue/tests.webpack.js b/libraries/vue/tests.webpack.js index a42a8d9a9d..637970640b 100644 --- a/libraries/vue/tests.webpack.js +++ b/libraries/vue/tests.webpack.js @@ -15,6 +15,91 @@ * limitations under the License. */ -// Run basic and advanced tests through Karma -require('./src/basic-tests.js'); -require('./src/advanced-tests.js'); +import {createApp, nextTick} from 'vue'; +import { + ComponentWithoutChildren, + ComponentWithChildren, + ComponentWithChildrenRerender, + ComponentWithDifferentViews, + ComponentWithProperties, + ComponentWithImperativeEvent, ComponentWithDeclarativeEvent, +} from "./src/components"; + +// Setup the test harness. This will get cleaned out with every test. +const container = document.createElement("div"); +document.body.appendChild(container); +let scratch; // This will hold the actual element under test. + +const isCustomElement = (tagName) => { + return window.customElements.get(tagName) !== undefined; +} + +beforeEach(function () { + scratch = document.createElement("div"); + scratch.id = "scratch"; + container.appendChild(scratch); +}); + +afterEach(function () { + container.innerHTML = ""; + scratch = null; +}); + +import basicTests from 'basic-tests'; +import advancedTests from 'advanced-tests'; + +function render(Component) { + const app = createApp(Component) + app.config.compilerOptions.isCustomElement = isCustomElement; + app.mount(scratch); + const wc = scratch.querySelector("#wc"); + return {wc} +} + +const renderers = { + renderComponentWithoutChildren() { + return render(ComponentWithoutChildren); + }, + renderComponentWithChildren() { + return render(ComponentWithChildren); + }, + async renderComponentWithChildrenRerender() { + const result = render(ComponentWithChildrenRerender); + // Waits for the tick in ComponentWithChildrenRerender's mount function + await nextTick(); + // Waits for the increment inside that tick to appear in the DOM. + await nextTick(); + return result; + }, + renderComponentWithProperties() { + return render(ComponentWithProperties); + }, + renderComponentWithDifferentViews() { + const { wc } = render(ComponentWithDifferentViews); + const toggler = scratch.querySelector('#toggler'); + async function toggle() { + toggler.click(); + await nextTick(); + } + return { wc, toggle } + }, + renderComponentWithImperativeEvent() { + const { wc } = render(ComponentWithImperativeEvent); + async function click() { + wc.click(); + await nextTick(); + } + return { wc, click } + }, + renderComponentWithDeclarativeEvent() { + const { wc } = render(ComponentWithDeclarativeEvent); + async function click() { + wc.click(); + await nextTick(); + } + return { wc, click } + } +} + +basicTests(renderers); +advancedTests(renderers); diff --git a/package-lock.json b/package-lock.json index 2f259051f0..5cb1028817 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,6 +53,32 @@ "mocha": "10.8.2" } }, + "libraries/__shared__/tests": { + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "chai": "4.3.10" + } + }, + "libraries/__shared__/tests/node_modules/chai": { + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", + "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + }, + "engines": { + "node": ">=4" + } + }, "libraries/__shared__/webcomponents": { "version": "1.0.0", "license": "ISC", @@ -14015,6 +14041,10 @@ "source-map": "^0.6.0" } }, + "node_modules/tests": { + "resolved": "libraries/__shared__/tests", + "link": true + }, "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", @@ -25182,6 +25212,29 @@ "terser": "^5.31.1" } }, + "tests": { + "version": "file:libraries/__shared__/tests", + "requires": { + "chai": "4.3.10" + }, + "dependencies": { + "chai": { + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", + "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.0.8" + } + } + } + }, "tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", diff --git a/package.json b/package.json index 26ddfbfd57..7cee7c84c0 100644 --- a/package.json +++ b/package.json @@ -84,6 +84,10 @@ "./libraries/__shared__/karma-plugins/karma-custom-html-reporter:build", "./libraries/__shared__/karma-plugins/karma-custom-json-reporter:build", "./libraries/__shared__/karma-plugins/karma-mocha:build" + ], + "files": [ + "./libraries/__shared__/tests/src/basic-tests.js", + "./libraries/__shared__/tests/src/advanced-tests.js" ] } } diff --git a/scripts/copy-and-verify-results.mjs b/scripts/copy-and-verify-results.mjs index d890101ae8..306bcf5d53 100644 --- a/scripts/copy-and-verify-results.mjs +++ b/scripts/copy-and-verify-results.mjs @@ -68,7 +68,7 @@ function compareResultsAgainstGoldens(library) { // A constant, to make sure that if we add/remove any tests, that we add that test to all // tested libraries. const numberOfTests = 32; - chai.assert.equal(actual.success + actual.failed, numberOfTests, `${library.name} has incorrect total tests`); + chai.assert.equal(actual.success + actual.failed + actual.skipped, numberOfTests, `${library.name} has incorrect total tests`); chai.assert.deepEqual(actual, expected, `${library.name} has incorrect deep results equal`); }