From 7a8b69ea872a2b31828549168a7a0210e08743e6 Mon Sep 17 00:00:00 2001 From: Jake Bentvelzen Date: Fri, 1 Feb 2019 13:34:43 +1100 Subject: [PATCH] fix(component-tester): fix bug where @containerless components wouldn't be initialized properly, this breaks the ability to manually call detached() lifecycle methods on the component for the time-being however (#12) Fixes #11 --- .../unit/containerless-div.test.ts | 17 +++++ lib/component-tester.ts | 74 ++----------------- src/containerless-div/containerless-div.html | 3 + src/containerless-div/containerless-div.ts | 11 +++ 4 files changed, 38 insertions(+), 67 deletions(-) create mode 100644 cypress/integration/unit/containerless-div.test.ts create mode 100644 src/containerless-div/containerless-div.html create mode 100644 src/containerless-div/containerless-div.ts diff --git a/cypress/integration/unit/containerless-div.test.ts b/cypress/integration/unit/containerless-div.test.ts new file mode 100644 index 0000000..d21f938 --- /dev/null +++ b/cypress/integration/unit/containerless-div.test.ts @@ -0,0 +1,17 @@ +import { PLATFORM } from 'aurelia-framework'; +import { bootstrap } from 'aurelia-bootstrapper'; +import { StageComponent } from 'cypress-aurelia-unit-test'; + +import { ContainerlessDiv } from '~/containerless-div/containerless-div'; + +describe('ContainerlessDiv', () => { + it('Test that we properly render a containerless component and calls attached() once', () => { + const component = StageComponent + .withResources(PLATFORM.moduleName('containerless-div/containerless-div')) + .inView(``); + component.create(bootstrap); + cy.get('containerless-div').should('not.exist'); + const AttachedMethodCalledCount = '1'; + cy.get(`div`).contains(AttachedMethodCalledCount); + }); +}); diff --git a/lib/component-tester.ts b/lib/component-tester.ts index a9c4804..d33701a 100644 --- a/lib/component-tester.ts +++ b/lib/component-tester.ts @@ -1,19 +1,17 @@ /// import 'reflect-metadata'; -import { Aurelia, Container, FrameworkConfiguration, ViewCompiler, ViewResources } from 'aurelia-framework'; +import { Aurelia, FrameworkConfiguration } from 'aurelia-framework'; import { DOM } from 'aurelia-pal'; -import { View } from 'aurelia-templating'; // NOTE(Jake): 2019-01-07 // Used by aurelia-testing. Keeping incase we want to reintroduce. // interface AureliaWithRoot extends Aurelia { // root: ViewWithControllers; // } - -interface ViewWithControllers extends View { - controllers: Array<{ viewModel: any }>; -} +// interface ViewWithControllers extends View { +// controllers: Array<{ viewModel: any }>; +// } // track the patches being used let patches = newPatches(); @@ -24,19 +22,6 @@ const aureliaDialogWarningMessage = 'aurelia-dialog causes Cypress to crash. Rem // and "losing" styles when the next test starts const stylesCache: Map> = new Map>(); -// track components that were attached so they can be detached before -// each build -const componentsAttached: any[] = []; - -function disposeComponents() { - for (const component of componentsAttached) { - if (component.detached) { - component.detached(); - } - } - componentsAttached.length = 0; -} - // NOTE: Jake: 2018-12-18 // Taken from: https://github.com/bahmutov/cypress-react-unit-test/blob/master/lib/index.js function copyStyles(componentName: string): void { @@ -89,10 +74,6 @@ export class _ { export class StageComponent { public static withResources(resources: string | string[] = []): ComponentTester { - // NOTE: Jake: 2018-12-19 - // Any components we tracked from the previous test, lets dispose them. - disposeComponents(); - // NOTE: Jake: 2018-12-19 // Clear document.body, this is so the first step of 2nd test won't have // the previous test rendered in it when you're debugging. @@ -112,7 +93,7 @@ export class ComponentTester { // private rootView: View; - private host: HTMLTemplateElement | HTMLDivElement | null = null; + // private host: HTMLTemplateElement | HTMLDivElement | null = null; private html: string = ''; @@ -206,51 +187,11 @@ export class ComponentTester { document.body.focus(); } - this.host = document.createElement('template'); - this.host.innerHTML = this.html; - - // Compile the template and copy styles to the main iframe - let view: ViewWithControllers; - const compiler = Container.instance.get(ViewCompiler); - try { - view = compiler.compile(this.host, Container.instance.get(ViewResources)).create(Container.instance); - } catch (err) { - reject(err); - return; - } - - if (view.controllers.length > 0) { - this.viewModel = view.controllers[0].viewModel; - if (this.viewModel) { - copyStyles(this.viewModel.constructor.name); - } else { - // tslint:disable-next-line:no-console - console.warn('No view model found on first controller. Styles might not work.', this.html); - } - } else { - // NOTE(Jake): 2018-12-19 - // Not sure if/when this case will execute or - // what the ramifications of this are. - copyStyles('undefined'); - // tslint:disable-next-line:no-console - console.warn('Unable to determine component name from template. Bugs may occur in cleanup.', this.html); - } - // Clear the document body and add child while (document.body.firstChild) { document.body.removeChild(document.body.firstChild); } - document.body.appendChild(view.fragment); - - // NOTE: Jake: 2018-12-20 - // Fix aurelia.enhance() problems that are occuring due to - // a in a component. - // Research: https://github.com/aurelia/framework/issues/600#issuecomment-252479570 - // Gist: https://gist.run/?id=c59eed72e1c255b8f462c1d45e495a7a - document.body.querySelectorAll('.au-target').forEach((el) => { - el.classList.remove('au-target'); - el.removeAttribute('au-target-id'); - }); + document.body.innerHTML = this.html; // NOTE: Jake: 2019-01-31 - #8 // Consider allowing bindingContext to be a function as well. @@ -263,6 +204,7 @@ export class ComponentTester { // These are in the original aurelia-testing library // this.rootView = aurelia.root; // this.element = this.host.firstElementChild as Element; + copyStyles(this.resources.join(',')); // NOTE: Jake: 2019-01-31 - #9 // We used to call these manually like the aurelia-testing library, @@ -275,8 +217,6 @@ export class ComponentTester { // view.attached(); // } - componentsAttached.push(view); - // Wait 4 frames, this allows us to do "hacky" CSS sizing calculations // that rely on requestAnimationFrame callbacks. This test framework // supports 4 by default. I might make this configurable in the future diff --git a/src/containerless-div/containerless-div.html b/src/containerless-div/containerless-div.html new file mode 100644 index 0000000..9081fc1 --- /dev/null +++ b/src/containerless-div/containerless-div.html @@ -0,0 +1,3 @@ + diff --git a/src/containerless-div/containerless-div.ts b/src/containerless-div/containerless-div.ts new file mode 100644 index 0000000..5d65b32 --- /dev/null +++ b/src/containerless-div/containerless-div.ts @@ -0,0 +1,11 @@ +import { autoinject, containerless } from 'aurelia-framework'; + +@autoinject +@containerless +export class ContainerlessDiv { + protected attachedCounter = 0; + + protected attached(): void { + this.attachedCounter += 1; + } +}