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

[Glimmer2] inline if #12920

Merged
merged 1 commit into from
Feb 24, 2016
Merged

[Glimmer2] inline if #12920

merged 1 commit into from
Feb 24, 2016

Conversation

GavinJoyce
Copy link
Member

part of the Glimmer Big-Picture Integration Checklist

TODO:

@@ -0,0 +1,11 @@
import { toBool as emberToBool } from './if-unless';

//TODO: GJ: docs
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rwjblue says the docs for if should be moved to this file.

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And thanks for noting this. In 1.13 we lost a ton of docs b/c PRs were merged without this stuff. Definitely worth doing up front.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, I'll do that

@homu
Copy link
Contributor

homu commented Feb 8, 2016

☔ The latest upstream changes (presumably #12924) made this pull request unmergeable. Please resolve the merge conflicts.

@GavinJoyce
Copy link
Member Author

I'm going to work on this later tonight and hopefully bring it to completion

@GavinJoyce
Copy link
Member Author

There are a number of shared tests which fail in htmlbars. For example, 6 of these fail (related issue):

moduleFor('Helpers test: {{if}} used with another helper', class extends SharedHelperConditionalsTest {
  templateFor({ cond, truthy, falsy }) {
    return `{{concat (if ${cond} ${truthy} ${falsy})}}`;
  }
});

I want to avoid marking these shared tests with a @glimmer prefix as that would result in them not being run for htmlbars for all other modules. Instead, I'm planning to add support for @glimmer and @htmlbars module prefixes. This would allow us skip these tests in htmlbars:

moduleFor('@glimmer Helpers test: {{if}} used with another helper', class extends SharedHelperConditionalsTest {
  templateFor({ cond, truthy, falsy }) {
    return `{{concat (if ${cond} ${truthy} ${falsy})}}`;
  }
});

@GavinJoyce
Copy link
Member Author

I'm seeing 14 test failures for both @htmlbars and @glimmer for the following set of tests:

moduleFor('@glimmer Helpers test: {{if}} used in attribute position', class extends SharedHelperConditionalsTest {
  templateFor({ cond, truthy, falsy }) {
    return `<div data-foo="{{if ${cond} ${truthy} ${falsy}}}" />`;
  }
  textValue() {
    return jQuery('div', this.element).toArray().map(
      function(el) { return jQuery(el).data('foo'); }
    ).join('');
  }
});

an example failing test is [glimmer] Helpers test: {{if}} used in attribute position: it considers empty arrays falsy. Do we expect these to pass for attributes? I'm going to take try create a failing test in glimmer2 now

@GavinJoyce GavinJoyce changed the title [wip] glimmer inline if [wip] glimmer2 inline if Feb 10, 2016
@chancancode
Copy link
Member

@GavinJoyce I think the problem is you didn't quote the "truthy" and "falsy" properly: it currently something like <div data-foo="{{if cond1 T1 F1}}" /> (which looks up T1 and F1 as properties on self) instead of <div data-foo="{{if cond1 'T1' 'F1'}}" />.

By the way, I think it will be better to add wrapperFor so that we can generate <div data-foo="{{if cond1 'T1' 'F1'}}{{if cond2 'T2' 'F2'}}{{if cond3 'T3' 'F3'}}" /> instead of <div data-foo="{{if cond1 'T1' 'F1'}}" /><div data-foo="{{if cond2 'T2' 'F2'}}" /><div data-foo="{{if cond3 'T3' 'F3'}}" />.

@GavinJoyce
Copy link
Member Author

@chancancode thanks, I'll implement the wrapperFor as you suggest.

I don't think it is a quoting problem, the renderValues function that I defined in SharedHelperConditionalsTest generates a template and context as follows:

<div data-foo="{{if cond1 t1 f1}}" /><div data-foo="{{if cond2 t2 f2}}" />
{"t1":"T1","f1":"F1","cond1":["hello"],"t2":"T2","f2":"F2","cond2":[]}

I can't immediately see why this isn't working, but I'm pretty sure I'm doing something wrong. I'll change it to use wrapperFor, the problem will likely go away.

@chancancode
Copy link
Member

Ah, you are right! I forgot that we changed it to be dynamic

@GavinJoyce
Copy link
Member Author

TODO: figure out why this passes:

moduleFor('Helpers test: {{if}} used in attribute position', class extends SharedHelperConditionalsTest {
  wrapperFor(templates) {
    return `<div>${templates.join('')}</div>`;
  }

  templateFor({ cond, truthy, falsy }) {
    return `{{if ${cond} ${truthy} ${falsy}}}`;
  }

  textValue() {
    return jQuery('div', this.element).text();
  }
});

but this doesn't:

moduleFor('Helpers test: {{if}} used in attribute position', class extends SharedHelperConditionalsTest {
  wrapperFor(templates) {
    return `<div data-foo="${templates.join('')}" />`;
  }

  templateFor({ cond, truthy, falsy }) {
    return `{{if ${cond} ${truthy} ${falsy}}}`;
  }

  textValue() {
    return jQuery('div', this.element).data('foo');
  }
});

@GavinJoyce
Copy link
Member Author

@paddyobrien solved this for me. It turns out that jQuery caches the data attribute values when accessing the values using:

jQuery('div', this.element).data('foo');

This solves it:

jQuery('div', this.element).attr('data-foo');

@chancancode
Copy link
Member

Ahh I see. It's probably good to use attr anyway so jQuery doesn't try to parse the text

@GavinJoyce GavinJoyce changed the title [wip] glimmer2 inline if Glimmer2 inline if Feb 11, 2016
@GavinJoyce
Copy link
Member Author

This is ready for review

@rwjblue
Copy link
Member

rwjblue commented Feb 11, 2016

@chancancode - Would you mind reviewing?

@chancancode
Copy link
Member

@GavinJoyce can you do me a favor and annotate the deleted test case with comments like these? #12914 (comment) We are trying to be careful to not lose coverage as we migrate these, and having those annotations would make it a lot easier to review! ❤️

The tests doesn't always have to be a direct port. We implicitly test a lot more things with the new harness/pattern, so it is quite possible we absorbed some existing test cases into other test cases implicitly (e.g. we used to have separate test cases for re-render, but we now test re-render all the time, so it makes sense to just delete it).

@GavinJoyce
Copy link
Member Author

@chancancode sure, I'll do that now


}, BASIC_TRUTHY_TESTS, BASIC_FALSY_TESTS);

moduleFor('@glimmer Helpers test: {{if}} used with another helper', class extends SharedHelperConditionalsTest {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@glimmer only as several of these tests fail in @htmlbars (see #12925)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😢

@GavinJoyce
Copy link
Member Author

@chancancode I've added a SharedHelperConditionalsTest version of the @htmlbars it does not update when the unbound helper is used test, as it needs a different template.

I've also added annotations for the two modules which are @glimmer only. I haven't removed any tests, the diff might look like it due to a few chunks of content moving around though.

QUnit.module(`[${packageName}] ${description}`, {
let modulePackagePrefixMatch = description.match(/^@(\w*)/); //eg '@glimmer' or '@htmlbars'
let modulePackagePrefix = modulePackagePrefixMatch ? modulePackagePrefixMatch[1] : '';
let descriptionWithoutPackagePrefix = description.replace(/^@\w* /, '');
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this adds support for module prefixes such as @glimmer and @htmlbars and is needed as the new comprehensive shared tests have highlighted some issues with htmlbars

@GavinJoyce
Copy link
Member Author

Let me know if you'd like me to annotate anything else

@chancancode
Copy link
Member

@GavinJoyce sorry! I should have looked more carefully – I copied the comment from here assuming it would make sense.

Can you review the existing tests and either delete (with the annotation) them or migrate them into the new test files? If some of them are too hard to port we can leave them in the old file and come back to them later; but I suspect your work already covered the majority of them, so seems good to have you review and delete them while your memory is still fresh.

Great work so far by the way, thank you so much for picking this up!!

@GavinJoyce
Copy link
Member Author

Ah, thanks for the clarification. Sure, I'll do that on Saturday which will be the next time I'll get to work on this.

I'm happy to continue working on glimmer2 integration once this has merged too, we're very excited to begin using it Intercom

return args[1];
} else {
let falsyArgument = args[2];
return falsyArgument === undefined ? '' : falsyArgument;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose this is needed to pass the tests at the moment? Can you add a TODO here? I believe we should unconditional return args[2] here (even if it's undefined) and let a different part of the system handle converting undefined, null, etc to "" (which we haven't implemented yet).

It's probably good to add a test for this case if we don't already have one (I think it would have to be @htmlbars for now), but perhaps that should be part of the general checklist item of "Add tests for rending false, undefined, null etc in content-test.js, similar to..."

this.render(`{{if condition truthy}}`, { condition: true, truthy: null });
this.render(`{{if condition truthy}}`, { condition: true, truthy: undefined });
this.render(`{{if condition truthy}}`, { condition: true, truthy: false });
...etc

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this was added to allow the moved it can omit the falsy argument test to pass. I'll modify this test to be @htmlbars and add a TODO as you suggest.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this got lost in the merge too, we retained the TODO comment but lost the @htmlbars marker

@GavinJoyce
Copy link
Member Author

@chancancode thanks for your feedback. I've made the following changes:

this.runTask(() => set(this.context, 'condition', true));

this.assertText('yes');
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

We should test both starting conditions (starting with true and starting with false), like this: https://github.com/emberjs/ember.js/blob/master/packages/ember-glimmer/tests/integration/syntax/if-unless-test.js#L52-L79

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, done

@chancancode
Copy link
Member

I ran out of time for this review session, I'll return to it another time! But I have left some "big picture" comments for you to chew on at the moment!

@GavinJoyce
Copy link
Member Author

Thanks for your feedback @chancancode. I'm keen to nail these testing patterns early so that the we can quickly and comprehensively integrate the rest of glimmer2 into ember

this.assertText('falsy');
}

['@test it updates when given a falsey second argument']() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤘 (I guess this must be a regression test?)

@@ -78,6 +86,7 @@ export class RenderingTest extends TestCase {
let owner = this.owner = buildOwner();
let env = this.env = new Environment({ dom, owner });
this.renderer = new Renderer(dom, { destinedForDOM: true, env });
this.$ = jQuery;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, this is not what I meant, I mean something like how this.$() works in components, but I can fix it

chancancode added a commit that referenced this pull request Feb 24, 2016
@chancancode chancancode merged commit 7c0befb into emberjs:master Feb 24, 2016
chancancode added a commit that referenced this pull request Feb 24, 2016
@chancancode
Copy link
Member

This is really awesome! Thanks for taking the time to work on this @GavinJoyce ❤️ 💚 💛 💙 💜

@GavinJoyce GavinJoyce deleted the gj/glimmer-inline-if branch February 24, 2016 22:16
@GavinJoyce GavinJoyce mentioned this pull request Feb 26, 2016
2 tasks
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

Successfully merging this pull request may close these issues.

5 participants