Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't get data bound fixtures to work with v3.0.0-rc.1 #47

Open
1 of 8 tasks
pghalliday opened this issue Mar 14, 2017 · 24 comments
Open
1 of 8 tasks

Can't get data bound fixtures to work with v3.0.0-rc.1 #47

pghalliday opened this issue Mar 14, 2017 · 24 comments

Comments

@pghalliday
Copy link

pghalliday commented Mar 14, 2017

Description

I tried to do the same as I did in Polymer 1.x with test-fixture v1.1.2, using the is="dom-template" attribute on my template and also tried using dom-bind as documented here https://www.polymer-project.org/2.0/docs/devguide/templates#dom-bind

But I cannot get data bound fixtures to work with a fresh polymer-2-application using test-fixture v3.0.0-rc.1

I suspect I'm doing something wrong :s

Expected outcome

Bound attributes are rendered with bound data

Actual outcome

Bound attributes are not rendered with bound data

Steps to reproduce

To a fresh polymer-2-application generated with polymer-cli v0.18.0-pre.13 (installs text-fixture v3.0.0-rc.1) add the following simple component as src/text.html

<link rel="import" href="../../../bower_components/polymer/polymer.html">

<dom-module id="my-text">
  <template>
    <div id="text">[[text]]</div>
  </template>
  <script>
    class MyText extends Polymer.Element {
      static get is() {
        return 'my-text';
      }

      static get properties() {
        return {
          text: String,
        };
      }
    }
    customElements.define(MyText.is, MyText);
  </script>
</dom-module>

And the following test as test/text.html

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">

    <title>my-list test</title>

    <script src="../../webcomponentsjs/webcomponents-lite.js"></script>
    <script src="../../web-component-tester/browser.js"></script>

    <link rel="import" href="../src/text.html">
  </head>
  <body>
    <test-fixture id="myText">
      <template is="dom-template">
        <my-text text="[[text]]"></my-text>
      </template>
    </test-fixture>
    <script>
      describe('my-text', function() {
        var myText;

        beforeEach(function(done) {
          myText = fixture('myText', {
            text: 'hello'
          });
          flush(done);
        });

        it('should display the text', function() {
          expect(myText.root.querySelector('#text').textContent).to.eql('hello');
        });
      });
    </script>
  </body>
</html>

Then run polymer test or wct, etc

The test fails with:

expected '[[text]]' to deeply equal 'hello'
  Context.<anonymous> at text.html:32

NB. The equivalent test with an equivalent polymer 1.x component succeeds

I also got this error in the console

test-fixture.html:296 test-fixture#myText "was given a model to stamp, but the template is not of a bindable type"
stamp @ test-fixture.html:296
createFrom @ test-fixture.html:200
(anonymous) @ test-fixture.html:176
forElements @ test-fixture.html:277
create @ test-fixture.html:174
fixture @ stub.js:3
(anonymous) @ VM528 text.html:25
callFnAsync @ mocha.js:4470
Runnable.run @ mocha.js:4420
next @ mocha.js:4801
(anonymous) @ mocha.js:4831
timeslice @ mocha.js:82

Browsers Affected

  • Chrome
  • Firefox
  • Safari 9
  • Safari 8
  • Safari 7
  • Edge
  • IE 11
  • IE 10

Aside

I also tried with the dom-bind element like this

    <test-fixture id="myText">
      <dom-bind>
        <template>
          <my-text text="[[text]]"></my-text>
        </template>
      </dom-bind>
    </test-fixture>

But that fails in both Polymer 1.x and the Polymer 2 RC with the following error

Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
     HTMLElement.<anonymous> at /components/test-fixture/test-fixture.html:271
     HTMLElement.forElements at /components/test-fixture/test-fixture.html:277
  HTMLElement.removeElements at /components/test-fixture/test-fixture.html:270
          HTMLElement.create at /components/test-fixture/test-fixture.html:172
         Context.<anonymous> at text.html:27
@jmorille
Copy link

jmorille commented Jun 9, 2017

I trying to migrate some polymer 1 to polymer 2 and I have the same bug
the following test working before migration to Polymer 2 with test-fixture#3.0.0-rc.1

<test-fixture id="ChangedPropertyTestFixture">
    <template is="dom-template">
        <my-text   url="{{url}}"></my-text>
    </template>
</test-fixture>
test('setting a property on the element works', function () {
    // Create a test fixture
    var element = fixture('ChangedPropertyTestFixture', {url: '/FiveElements/air'}); 
    assert.equal(element.url, '/FiveElements/air');
 });

with the current error

 expected '{{url}}' to equal '/FiveElements/air'

with the current log in console

'was given a model to stamp, but the template is not of a bindable type'

in reference of the code of test-fixture that test if (fixtureTemplate.stamp)

    stamp: function (fixtureTemplate, model) {
      var stamped;
      // Check if we are dealing with a "stampable" `<template>`. This is a
      // vaguely defined special case of a `<template>` that is a custom
      // element with a public `stamp` method that implements some manner of
      // data binding.
      if (fixtureTemplate.stamp) {
        stamped = fixtureTemplate.stamp(model);
        // We leak Polymer specifics a little; if there is an element `root`, we
        // want that to be returned.
        stamped = stamped.root || stamped;

      // Otherwise, we fall back to standard HTML templates, which do not have
      // any sort of binding support.
      } else {
        if (model) {
          console.warn(this, 'was given a model to stamp, but the template is not of a bindable type');
        }

question: need to still use is="dom-template" with fixture with model ?

NB: This regression is a big probem for migrate to polymer 2 if the unit testing not fulling working

@ppeou
Copy link

ppeou commented Jun 17, 2017

Hello,
I am facing same issue. Any help resolving this issue is greatly appreciated.

@srsudar
Copy link

srsudar commented Jul 2, 2017

I've tried both a bare <template is="dom-template"> and one wrapped with <dom-bind>, and I see the same errors as @pghalliday .

srsudar added a commit to srsudar/SemCache that referenced this issue Jul 2, 2017
It looks like there is an open bug on Polymer 2.0 and wct 6 that data
binding is broken:

PolymerElements/test-fixture#47

This is a huge problem, and I don't understand why it remains open after
being opened in March. However, the functionality is important enough
that, for now, I am going to begrudgingly allow it to break.
@srsudar
Copy link

srsudar commented Jul 3, 2017

Messing around with this some more, I remain confused. There are a lot of things that confuse me writing Polymer apps, including wct and polymer-cli versions. I've forked test-fixture and have tried to write a test that requires data binding. Thus far I've failed, but I'm not at all sure this isn't due to a Polymer/WCT version issue that eludes me.

Nevertheless, what I describe below is odd and might help someone who knows more than I do.

I've added a test case like the following in test/test-fixture.html:

DOM:

  <test-fixture id="DataBindingFixture">
    <dom-bind>
      <template is="dom-template">
        <div id="stamp-me">
          {{textValue}}
        </div>
      </template>
    </dom-bind>
  </test-fixture>

Test:

    describe('for a dom with a bound template', function () {
      var el;
      let model = {
        textValue: 'I should be stamped',
      };

      beforeEach(function () {
        debugger; // lets you step in and see the removeChild() problem
        el = dataBindingFixture.create(model);
      });

      it('div text should be stamped', function () {
        var div = document.getElementById('stamp-me');
        expect(document.getElementById('stamp-me').innerText)
          .to.equal(model.textValue);
      });
    });

That test fails with the Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node. error reported above. Omitting the <dom-bind> element just causes the test to fail at the assert statement.

What really boggles my mind about this is that when I step through the code, the element that supposedly is not a child certainly looks like it is a child. This console screenshot is taken with the debugger on the line:

this.removeChild(element);

Looking at this and element, it certainly looks like element is a child. What is really strange is that, after manually invoking removeChild(element) and seeing the error that element is not a child, inspecting this again still indicates that element is a child! Very odd.

screen shot 2017-07-02 at 10 19 38 pm

@pdesjardins90
Copy link

@cdata (Please file a bug re: data-bound templates. ) that was already filed I guess

@MrMcGibblets
Copy link

Was the bug mentioned above filed? if so can it be linked to this one, please?

@pdesjardins90
Copy link

It was just a discussion on twitter that resulted in me opening an issue, but this issue was exactly what we were talking about

@MrMcGibblets
Copy link

ah ok, so no movement as of yet.

Thanks

@ErikGrimes
Copy link

To workaround the issue, wrap the <test-fixture> in a <dom-bind>.

<dom-bind>
   <test-fixture>
       <template>
            <paper-icon-button icon="[[icon]]"></paper-icon-button>
       </template>
   </test-fixture>
</dom-bind>

Then update the bound data using the DomBind.set.

document.querySelector('dom-bind').set('icon','clear');

@ansreng
Copy link

ansreng commented Oct 18, 2017

@ErikGrimes your solution doesn't seem to work for me.

Any new comments from the developers?

@pdesjardins90
Copy link

pdesjardins90 commented Oct 18, 2017

For everyone's information, type-extension elements (<.. is="...">) doesn't work anymore in Polymer 2 (see the what's new section), so that's why <template is="dom-template"> doesn't work like before.

The expected behavior of the new version should be that it works with a straight <template>, or some kind of <dom-template> implementation

@cdata can you please provide an update on this?

@bkkujala
Copy link

I can verify the <dom-bind> approach. The document.querySelector('dom-bind').set works as above, I was also able to use document.querySelector('dom-bind').get in a test that uses firebase:

<dom-bind>
  <test-fixture id="testUser">
    <template>
      <firebase-auth 
           id="auth" 
           app-name="my-app" 
           user="{{user}}"></firebase-auth>
      <!-- More test omitted here -->
    </template>
  </test-fixture>
</dom-bind>

Then in my test I used:

describe('My test', function() {
  before(function() { 
    var auth = document.getElementById('auth');
    var dbind = document.querySelector('dom-bind');
    const email = '[email protected]';
    const pass = '****';
    auth.signInWithEmailAndPassword(email, pass).then(function(){
      var uid = dbind.get('user').uid;
      /* Wrote some test data to a location that used the user uid */
    });
  });
  it('should do something', function () {
      /* actual test was on an element that read from firebase in a location based on the 
          authorized user id and returned a value... */
  });
});

I didn't end up using the fixture javascript function in the test. I never managed to get it to work as expected which is likely because of the extra nesting...

@ernsheong
Copy link

ernsheong commented Dec 7, 2017

Workaround 🤷‍♂️

test("displays text", (ok) => {
  const element = fixture(Fixture.BASIC);
  element.data = {
    foo: true,
  };

  setTimeout(() => {
    const foo = element.shadowRoot.querySelector("#some-id").textContent;
    assert.equal(
      foo,
      "bar",
    );

    ok();
  });
});

@rgladwell
Copy link

Can confirm this is also happening in Firefox.

@rgladwell
Copy link

I wrote a failing test for this issue, can someone take a look at it to see if it checks out:

https://github.com/rgladwell/test-fixture/commit/b9db992245f1ef19cb7f8f42e699a9d001269be9

@vjeetje
Copy link

vjeetje commented May 7, 2018

The dom-bind work-around isn't working for me in Polymer 2.2.0

@dman777
Copy link

dman777 commented Jun 12, 2018

For Polymer 1.* the dom bind works great.

The issue I was experiencing was the testing browser was caching my old test with the -p option for persistence. I kept getting breakage/failure because my new changes weren't taking effect when refreshing my testing browser.

Make sure you are clearing your browser cache in your unit testing.

@rom1504
Copy link

rom1504 commented Sep 19, 2018

Hi, any working work around ?
Nothing works for polymer 3

@rom1504
Copy link

rom1504 commented Sep 19, 2018

a working workaround is to put a setTimeout in the ready of your component

@dman777
Copy link

dman777 commented Sep 20, 2018

@rom1504 here is how I do it in Polymer 1 if that helps any.
Be sure to use Mocha's sync feature:

    <test-fixture id="monthly-income-form-edit">
      <template is="dom-template">
        <h2>monthly income edit form</h2>
        <monthly-income-form-edit
          fields="[[fields]]"
          picklist-values="[[picklistValues]]"
          answers="[[answers]]"
        ></monthly-income-form-edit>
      </template>
    </test-fixture>

....

        beforeEach((done) => {
           myEl = fixture('monthly-income-form-edit',
              { 
                answers: answersMock,
                fields: fieldsMock,
                picklistValues: picklistMock
              });
         
          setTimeout(()=> {
           do stuff you need in the dom after it's initialize
           done()
          }, 1);

@rom1504
Copy link

rom1504 commented Sep 20, 2018 via email

@kevinpschaaf
Copy link

Here's a little snippet that might unblock users needing this legacy functionality in tests: https://jsbin.com/jihunuy/edit?html,output

This adds a stamp method on <template is="dom-template"> elements that makes them compatible with <test-fixture>. As long the "helper code" there is run after test fixtures are parsed and before any test fixtures are created in tests, it should work.

@rom1504
Copy link

rom1504 commented Jan 11, 2019 via email

@leegee
Copy link

leegee commented Jan 22, 2019

"Legacy"?! If this module is not intended to be compatible with Polymer > 2.2.0, shouldn't it be removed from the Polymer 3.0 docs?

qtprojectorg pushed a commit to qtqa/gerrit that referenced this issue Sep 25, 2019
Polymer 2 doesn't support binding in test-fixture (see
PolymerElements/test-fixture#47).
Another problem that pluginLayers can be set null - additional
check was added.

Change-Id: I48c3fbaab6763867bd872ba10507a6dbd7ddf732
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests