Skip to content

✅ buildDom: add tests for amp-fit-text and amp-layout#35494

Merged
samouri merged 2 commits intoampproject:mainfrom
samouri:test-bd
Aug 3, 2021
Merged

✅ buildDom: add tests for amp-fit-text and amp-layout#35494
samouri merged 2 commits intoampproject:mainfrom
samouri:test-bd

Conversation

@samouri
Copy link
Copy Markdown
Member

@samouri samouri commented Aug 2, 2021

summary
Adds basic unit tests for buildDom in both amp-fit-text and amp-layout. The tests assert that the outerHTML result of calling buildCallback and buildDom should be the same for a given component.

cc @ampproject/wg-performance

buildDom(fitText2);

expect(fitText1.outerHTML).to.equal(fitText2.outerHTML);
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I wish there were a way to share this test case/make it easily reusable since it'll be needed everywhere, but I'm not sure what that would look like

Copy link
Copy Markdown
Member Author

@samouri samouri Aug 2, 2021

Choose a reason for hiding this comment

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

I was considering putting it all in a single file, within src/compiler/test/test-buildDom. Then we could abstract out a testBuildDom that takes in a tagName and Ctor.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I like that idea, but it seemed to get more complicated when I thought through it. The helper would need some way of getting the buildDom function itself from the tagName, or it would have to be passed in, right? I was thinking the helper could take element, Ctor, and buildDom possibly

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

You're right, I forgot about buildDom, it would need that too. So the test file would look like:

const tests = [
  {tagName: 'amp-fit-text', buildDom: fitTextBuildDom, Ctor: AmpFitText },
  ...
]

tests.forEach(({Ctor, tagName, buildDom})=> {
  it('buildDom and buildCallback should result in the same outerHTML', () => {
     const el1 = createElementWithAttributes(tagName, {height: 10, width: 10});
     const el2 = el1.cloneNode(true);

     await (new Ctor(el1).buildCallback())
     buildDom(el2);
     expect(el1.outerHTML).to.equal(el2.outerHTML)
  })
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I disliked the idea when it was a helper function that different test files would import, but seeing it like this where all the components and functions/ctors are listed in one place, I like it much more. We can even do it(`${tagName} - buildDom..` => {...}) so the test output is a bit more meaningful.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

hah, i asked about this about a moon ago. where should the file live?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is there a file anywhere that will be creating/exporting the instruction map? If so, it would make a lot of sense for this to be something like test-instruction-map and then the file itself would have a const constructorMap and compare the results

Copy link
Copy Markdown
Member Author

@samouri samouri Aug 3, 2021

Choose a reason for hiding this comment

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

Yes. Within src/compiler/builders.js...but I'm not confident src/compiler is the right directory for this test

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Neither am I. Maybe we export a helper function that takes tagName, Ctor and itself uses the instruction map to look up the buildDom function, that way calling code can do something like itMatchesBuildDom('amp-fit-text', AmpFitText); or something like that

@samouri samouri requested a review from caroqliu August 2, 2021 22:22
Copy link
Copy Markdown
Contributor

@caroqliu caroqliu left a comment

Choose a reason for hiding this comment

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

LGTM with a question

});
const fitText2 = fitText1.cloneNode(/* deep */ true);

new AmpFitText(fitText1).buildCallback();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

FMI: What's the difference between building these two ways below?
1:

new AmpFitText(fitText1).buildCallback();

2:

fitText1.buildInternal();

I've always done (2) because it avoids having to export and import the component class, but I'm wondering if there should be any difference in outcome otherwise?

While we are here, would you want another test with runtimeOn: true and await fitText1.whenBuilt()?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

For most tests (2) is the more correct thing to do. Since we want to simulate everything the Runtime would do. That makes sense when testing the component's behavior. All the classNames additions etc. are required. In order to use (2), you also need to add the element to the document or else there will be errors finding the ampdoc.

For these tests, the goal is to ensure buildCallback and buildDom result in the same DOM Mutations -- completely isolated from the rest of the mutations that would occur during Runtime bootstrap of an element.

Copy link
Copy Markdown
Member Author

@samouri samouri Aug 3, 2021

Choose a reason for hiding this comment

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

As an example, i-amphtml-notbuilt is during createdCallback flow of the CE after being added to the DOM. buildInternal will then remove that. This sequence of classNames is unrelated to what I'd like to test

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I see, this helps a lot. Thanks for the explanation!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'm really not confident about the "most tests" part. Don't have a great understanding of what we want "unit test" to mean for components (i.e. runtime on or no)

@samouri samouri enabled auto-merge (squash) August 3, 2021 14:20
@samouri samouri merged commit 42c553e into ampproject:main Aug 3, 2021
@samouri samouri deleted the test-bd branch August 3, 2021 14:52
westonruter added a commit to westonruter/amphtml that referenced this pull request Aug 3, 2021
…tok-validation

* 'main' of github.com:ampproject/amphtml: (72 commits)
  build: run amp lint --fix to address import order of jixie (ampproject#35513)
  ✨ [amp-analytics] Add Custom Browser Event Tracker (ampproject#35193)
  babel: teach amp mode transformer about #core/mode (ampproject#35477)
  🚮 Remove experiment `amp-consent-granular-consent` (ampproject#35508)
  ♻️ Enable auto-sorting+grouping within src/ and 3p/ (ampproject#35454)
  🐛  [amp-render] fix root-element stripping from amp-render with amp-bind (ampproject#35449)
  ✅ [Story interactive] Add Example Story for Detailed Results Component (ampproject#35450)
  🐛 Fix error on bento example (ampproject#35490)
  🐛 amp-story-grid-layer: Fix AMP invalidation error in documentation (ampproject#35503)
  🐛 Fix code formatting (ampproject#35499)
  ✅ buildDom: add tests for amp-fit-text and amp-layout (ampproject#35494)
  ♻️ Remove unused imports (ampproject#35435)
  ✨ amp-connatix-player: iframe domain based on a property (ampproject#35179)
  Updated document with use cases of remote config (ampproject#35496)
  AMP.goBack: update documentation (ampproject#29290)
  🏗 Allow the bundle-size job to run even if the builds were skipped (ampproject#35492)
  build-system: improve terser/esbuild integration (ampproject#35466)
  🧪 [Story performance] Disable animations on first page to 50% (ampproject#35476)
  📖 [Amp story] [Page attachments] Amp.dev Docs for New Page Attachment Features ampproject#34883 (ampproject#35338)
  🚀 [Story interactive] Rewrite Image URL to Cached URL for Image Quizzes and Polls (ampproject#35375)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants