#135 | Screenshot 2019-06-22 at 01.11.30.png | 1.92 MB | Wim Leers |
#132 | 3052482-132.patch | 60.44 KB | Wim Leers |
|
#132 | interdiff.txt | 8.22 KB | Wim Leers |
#131 | 3052482-131.patch | 60.81 KB | Wim Leers |
|
#131 | interdiff.txt | 3.32 KB | Wim Leers |
#128 | 3052482-128.patch | 60.76 KB | Wim Leers |
|
#128 | interdiff.txt | 2.93 KB | Wim Leers |
#127 | 3052482-127.patch | 60.89 KB | Wim Leers |
|
#127 | interdiff.txt | 662 bytes | Wim Leers |
#126 | 3052482-126.patch | 60.95 KB | Wim Leers |
|
#126 | interdiff.txt | 8.98 KB | Wim Leers |
#125 | 3052482-125.patch | 61.57 KB | Wim Leers |
|
#125 | interdiff.txt | 4.53 KB | Wim Leers |
#124 | 3052482-124.patch | 61.66 KB | Wim Leers |
|
#124 | interdiff.txt | 6.41 KB | Wim Leers |
#123 | 3052482-123.patch | 58.5 KB | Wim Leers |
|
#123 | interdiff.txt | 9.48 KB | Wim Leers |
#122 | 3052482-122.patch | 59.16 KB | Wim Leers |
|
#122 | interdiff.txt | 4.8 KB | Wim Leers |
#121 | 3052482-121.patch | 59.84 KB | Wim Leers |
|
#121 | interdiff.txt | 4.22 KB | Wim Leers |
#120 | 3052482-120.patch | 60.49 KB | Wim Leers |
|
#120 | interdiff.txt | 7.52 KB | Wim Leers |
#119 | 3052482-119.patch | 59.91 KB | Wim Leers |
|
#119 | interdiff.txt | 5.41 KB | Wim Leers |
#118 | 3052482-118.patch | 60.72 KB | Wim Leers |
|
#118 | interdiff.txt | 15.86 KB | Wim Leers |
#117 | 3052482-117.patch | 60.62 KB | Wim Leers |
|
#117 | interdiff.txt | 5 KB | Wim Leers |
#116 | 3052482-116.patch | 61.42 KB | Wim Leers |
|
#116 | interdiff.txt | 1.87 KB | Wim Leers |
#115 | 3052482-115.patch | 61.25 KB | Wim Leers |
|
#115 | interdiff.txt | 2.98 KB | Wim Leers |
#114 | 3052482-114.patch | 60.64 KB | Wim Leers |
|
#114 | interdiff.txt | 5.16 KB | Wim Leers |
#113 | 3052482-113.patch | 61.35 KB | Wim Leers |
|
#113 | interdiff.txt | 3.9 KB | Wim Leers |
#112 | 3052482-112.patch | 60.89 KB | Wim Leers |
|
#112 | interdiff.txt | 3.57 KB | Wim Leers |
#107 | 3052482-107.patch | 61.93 KB | Wim Leers |
|
#107 | interdiff.txt | 9.35 KB | Wim Leers |
#105 | 3052482-105.patch | 62.59 KB | Wim Leers |
|
#105 | interdiff.txt | 5.11 KB | Wim Leers |
#104 | 3052482-104.patch | 61.05 KB | Wim Leers |
|
#104 | interdiff.txt | 3.08 KB | Wim Leers |
#103 | 3052482-103.patch | 61.11 KB | Wim Leers |
|
#103 | interdiff.txt | 3.17 KB | Wim Leers |
#102 | 3052482-102.patch | 61.05 KB | Wim Leers |
|
#102 | interdiff.txt | 711 bytes | Wim Leers |
#101 | 3052482-101.patch | 61.04 KB | Wim Leers |
|
#101 | interdiff.txt | 4.87 KB | Wim Leers |
#100 | interdiff.txt | 3.82 KB | Wim Leers |
#100 | 3052482-100.patch | 61.19 KB | Wim Leers |
|
#99 | 3052482-98.patch | 59.95 KB | Wim Leers |
|
#99 | interdiff.txt | 9.46 KB | Wim Leers |
#95 | 3052482-95.patch | 56.12 KB | Wim Leers |
|
#95 | interdiff.txt | 4.36 KB | Wim Leers |
#93 | 3052482-93.patch | 56.84 KB | Wim Leers |
|
#93 | interdiff.txt | 5.27 KB | Wim Leers |
#92 | 3052482-92.patch | 57.14 KB | Wim Leers |
|
#92 | interdiff.txt | 4.06 KB | Wim Leers |
#90 | interdiff.txt | 2.81 KB | Wim Leers |
#90 | 3052482-90.patch | 57.34 KB | Wim Leers |
|
#89 | 3052482-89.patch | 57.21 KB | Wim Leers |
|
#89 | interdiff.txt | 6.98 KB | Wim Leers |
#87 | 3052482-87.patch | 57.7 KB | Wim Leers |
|
#87 | interdiff.txt | 7.62 KB | Wim Leers |
#86 | 3052482-86.patch | 58.42 KB | Wim Leers |
|
#86 | interdiff.txt | 2 KB | Wim Leers |
#82 | 3052482-82.patch | 58.59 KB | Wim Leers |
|
#82 | interdiff.txt | 3.06 KB | Wim Leers |
#81 | 3052482-81.patch | 58.66 KB | Wim Leers |
|
#81 | interdiff.txt | 2.14 KB | Wim Leers |
#80 | 3052482-80.patch | 58.72 KB | Wim Leers |
|
#80 | interdiff.txt | 3.41 KB | Wim Leers |
#79 | 3052482-79.patch | 58.66 KB | Wim Leers |
|
#79 | interdiff.txt | 3.39 KB | Wim Leers |
#78 | 3052482-78.patch | 57.49 KB | Wim Leers |
|
#78 | interdiff.txt | 2.23 KB | Wim Leers |
#77 | 3052482-77.patch | 59.66 KB | Wim Leers |
|
#77 | interdiff.txt | 16.13 KB | Wim Leers |
#76 | 3052482-76.patch | 58.56 KB | Wim Leers |
|
#76 | interdiff.txt | 1.14 KB | Wim Leers |
#75 | 3052482-75.patch | 58.72 KB | Wim Leers |
|
#75 | interdiff.txt | 3.42 KB | Wim Leers |
#74 | 3052482-73.patch | 57.13 KB | Wim Leers |
|
#74 | interdiff.txt | 1.92 KB | Wim Leers |
#72 | 3052482-72.patch | 57.32 KB | Wim Leers |
|
#72 | interdiff.txt | 838 bytes | Wim Leers |
#67 | 3052482-67.patch | 57.31 KB | Wim Leers |
|
#67 | interdiff.txt | 5.4 KB | Wim Leers |
#66 | 3052482-66.patch | 57.11 KB | Wim Leers |
|
#66 | interdiff.txt | 2.67 KB | Wim Leers |
#65 | 3052482-65.patch | 57.86 KB | Wim Leers |
|
#65 | interdiff.txt | 2.48 KB | Wim Leers |
#63 | 3052482-63.patch | 58.87 KB | Wim Leers |
|
#63 | interdiff.txt | 2.52 KB | Wim Leers |
#62 | 3052482-62.patch | 59.17 KB | Wim Leers |
|
#62 | interdiff-ported-54.txt | 2.55 KB | Wim Leers |
#62 | interdiff-ported-51_and_53.txt | 3.49 KB | Wim Leers |
#61 | 3052482-61.patch | 58.73 KB | Wim Leers |
|
#61 | interdiff.txt | 13.33 KB | Wim Leers |
#60 | 13151825-60.patch | 64.64 KB | oknate |
|
#60 | 13151825--interdiff-56-60.txt | 1.42 KB | oknate |
#56 | 13151825-56.patch | 64.17 KB | oknate |
|
#56 | 13151825--interdiff-54-56.txt | 19.65 KB | oknate |
#54 | 13151825--interdiff-53-54.txt | 2.39 KB | oknate |
#54 | 13151825-54.patch | 66.68 KB | oknate |
|
#53 | 13151825-53.patch | 66.23 KB | oknate |
|
#53 | 13151825--interdiff-49-53.txt | 1.65 KB | oknate |
#51 | 13151825-49.patch | 66.26 KB | oknate |
|
#51 | 13151825-interdiff--48-49.txt | 2.94 KB | oknate |
#49 | 3052482-48.patch | 59.77 KB | Wim Leers |
|
#49 | interdiff.txt | 1.38 KB | Wim Leers |
#47 | 3052482-47.patch | 59.61 KB | Wim Leers |
|
#47 | interdiff.txt | 10.36 KB | Wim Leers |
#43 | 3052482-43.patch | 53.38 KB | Wim Leers |
|
#43 | interdiff.txt | 2.48 KB | Wim Leers |
#40 | 3052482-40.patch | 53.55 KB | wannesdr |
|
#40 | 3052482-40-interdiff.txt | 4.83 KB | wannesdr |
#38 | 3052482-38-interdiff.txt | 1.73 KB | wannesdr |
#38 | 3052482-38.patch | 53.77 KB | wannesdr |
|
#37 | 3052482-37.patch | 54.14 KB | wannesdr |
|
#37 | 3052482-37-interdiff.txt | 1.54 KB | wannesdr |
#34 | 3052482-34.patch | 54.13 KB | wannesdr |
|
#34 | 3052482-34-interdiff.txt | 1.11 KB | wannesdr |
#32 | 3052482-32.patch | 54.1 KB | wannesdr |
|
#32 | 3052482-32-interdiff.txt | 8.54 KB | wannesdr |
#31 | 3052482-31-interdiff.txt | 539 bytes | wannesdr |
#31 | 3052482-31.patch | 54.4 KB | wannesdr |
|
#29 | 3052482-28-interdiff.txt | 1.06 KB | wannesdr |
#29 | 3052482-28.patch | 54.32 KB | wannesdr |
|
#27 | 3052482-27.patch | 54.31 KB | wannesdr |
|
#27 | 3052482-27-interdiff.txt | 33.76 KB | wannesdr |
#25 | 3052482-25-interdiff.patch | 7.65 KB | wannesdr |
|
#25 | 3052482-25.patch | 48.78 KB | wannesdr |
|
#24 | 3052482-22.patch | 49.51 KB | wannesdr |
|
#21 | 3052482-21.patch | 15.76 KB | wannesdr |
|
#21 | 3052482-21-interdiff.txt | 15.78 KB | wannesdr |
#18 | entity-embed-3059394-18.patch | 46.17 KB | oknate |
|
#12 | 3052482--interdiff-11-12.txt | 1016 bytes | oknate |
#12 | entity-embed-filter-test-revamp-3052482-12.patch | 43.9 KB | oknate |
|
#11 | 3052482--interdiff-9-11.txt | 10.21 KB | oknate |
#11 | entity-embed-filter-test-revamp-3052482-11.patch | 43.89 KB | oknate |
|
#10 | entity-embed-filter-test-revamp-3052482-10.patch | 35.23 KB | oknate |
|
#9 | entity-embed-filter-test-revamp-3052482-9.patch | 34.3 KB | oknate |
|
#9 | 3052482--interdiff-7-9.txt | 5.07 KB | oknate |
#7 | 3052482--interdiff-6-7.txt | 18.42 KB | oknate |
#7 | entity-embed-filter-test-revamp-3052482-7.patch | 31.43 KB | oknate |
|
#6 | entity-embed-filter-test-revamp-3052482-6.patch | 14.3 KB | oknate |
|
#4 | entity-embed-filter-test-revamp-3052482-4.patch | 7.75 KB | oknate |
|
#3 | 3052482-3.patch | 5.32 KB | marcoscano |
|
Comments
Comment #2
Wim LeersComment #3
marcoscanoStarted working on this, but ran out of time.
Tried to create a unit test but it was quite hard with so many services needed to render the entity inside the filter. The Kernel test seems more doable though, here is the baseline of what I was thinking for it. Will continue with the other test cases as soon as I find more time :) .
Comment #4
oknateI started working on this as well. I'm taking a different approach. I think it'll be easier to iteratively update the existing test until we've removed anything that would require the browser, and only then convert it to a Kernel test and leave in a browser test anything that requires the browser test.
Another thing I'm working on, is these embeds are a little hard to read because they are long strings, so they go out of the viewport in my IDE. So I want to use DomDocument to allow arrays of attributes to be used in the tests so they are more vertical and therefore easier to read.
This will come in handy when comparing variants with slight differences in attributes, I think.
Comment #5
Wim LeersMany thanks, both of you!
#3:
I know, unit tests are hard when doing rendering!
Great start, thanks!
Reported independently, and being fixed over at #3054873: Hidden dependency on node module :)
#4: You may be right. I have no strong preference about how we get there. As long as we get there :)
I see what you're saying with the painful assertions. I encountered the same problem. That's why as part of #2752253-42: Document correct filter_html_image_secure + filter_align + filter_caption + entity_embed filters order, write tests, and ensure correct by default, I started converting those
$this->assertRaw('LONG HTML STRING')
calls to something like$this->assertSession()->elementExists('css', 'figure.caption-drupal-entity.align-left div.embedded-entity[data-entity-embed-display="entity_reference:entity_reference_entity_view"][data-entity-embed-display-settings="full"][data-entity-type="node"][data-entity-uuid="' . $this->node->uuid() . '"][data-view-mode="some-invalid-view-mode"][data-langcode="en"]');
. I like how you're taking it even further.Does either of you have time to continue this in the next days or week?
Comment #6
oknateI made a little more progress. While I haven't spent that much time on it, I got stuck on published vs not published and the caption display. Those are out of the scope of the filter, so my way of generating the markup for those assertions is too limited:
We could possibly leave those ones in place when we move the others ones to a kernel test. I'm pretty busy the next week, but will try to work on it.
Comment #7
oknateMore progress on converting the existing tests to not use drupalGet(), so they'll be easier to convert to kernel tests.
Oh and I figured out the caption display. It's a separate filter. So I was able to convert those tests.
Comment #8
oknateI realize that most of the existing tests are nodes. So we could convert them to embedding media instead, or duplicate them.
I also haven't added any more edge cases yet. So we'll have to scour the functionality of the module to find more edge cases to test.
Also, I believe @marcoscano's test is media specific, so we may want to end up with two test classes.
Comment #9
oknateMore progress removing getDrupal calls in the original test. Now all of those are gone from testFilter() method. There's still the testTranslation() method to do, and to convert this to a Kernel test.
Comment #10
oknateLast patch (#9) was missing latest changes. Here's the corrected patch.
It looks like I reverted some changes from #3042600 when I merged those changes in, so I'll need to go back through the patch and fix that.
After looking through the patch, this looks like the only place that happened. And this is because I had failed to convert this section over to the new test format.
Comment #11
oknateUpdated testTranslation() method to remove getDrupal calls.
Comment #12
oknateCombining the two tests cuts the run time from 30 seconds to 17 seconds. With reducing runtime being the goal of a Kernel test, I'll combine them.
Comment #13
oknateIn regard to
AFAIK, entity embed doesn't support embedding revisions.
Comment #14
Wim LeersWoah, massive progress since I last reviewed this! 🥳 💪
#12:
Kernel tests already run much faster than functional tests. Let's not combine them, because then we will eventually end up with a single multi-thousand line method that is impossible to understand. Let's keep them scoped as before.
EDIT: this actually will probably become irrelevant if we start using a
@dataProvider
like I suggested below :)#13: you're right. Ignore that bullet :) Removed it.
This has not yet been converted to a kernel test. Even though much of the
setUp()
method is already prepared for operating in a kernel test: it's very similar to\Drupal\Tests\filter\Kernel\FilterKernelTest::setUp()
, where\Drupal\Tests\filter\Kernel\FilterKernelTest::testAlignFilter()
and\Drupal\Tests\filter\Kernel\FilterKernelTest::testCaptionFilter()
are good examples to consider.This is now ideally prepared to be converted to a test using a
@dataProvider
. The quoted comment would be the array key (describing a particular test case) and the parameters forgetEmbedCode()
would be the first array value, plus additional array values for each of the expectations below.So something like
This will:
A) allow each test case to run independently, meaning that if one of the earlier cases fails, the others are still evaluated, which makes the test suite MUCH more useful
B) therefore it becomes 100x easier to debug regressions
C) make it much easier to get a sense of the various test cases that exist
Good examples of this pattern:
\Drupal\Tests\big_pipe\Unit\Render\Placeholder\BigPipeStrategyTest
and\Drupal\Tests\layout_builder\Kernel\DefaultsSectionStorageTest::providerTestAccess()
.If you want, I'm happy to explain it more detail. :) Or start doing this for a subset of it.
Comment #15
oknateI think I understand. So no more explanation needed. If you want to jump in and do the data provider yourself, that's cool. Otherwise, I'll take a stab at it. The part I had trouble with was converting it to a Kernel test. I think it might take me a few hours to figure out, and it was frustrating, so I haven't tried again yet. If you want to give it a go, or if you can convince a masochist like phenaproxima to figure that part out, that would be welcome. Although I'm willing to work on it, when I feel ready.
Comment #16
oknateNow that I think about it, I think I should do the data provider stuff. It'll be good practice for me, as I haven't used data providers that much, and it would be a waste of your time, when you have all this amazing stuff to do with the javascript. So at least with the data provider stuff, I'll do it.
Comment #17
Wim Leers🥳👍
Yeah I was in your place a few years ago, I first wasn't entirely convinced by its value, but once I got the hang of it, MAN IS IT AWESOME! Seems superfluous now, but wait until you run into a bug that breaks just this one edge case. It's such a time saver then.
WRT converting to kernel test: I'll try to do that today.
Comment #18
oknateI started on the data provider. This is a work in progress. I'll work on it more over the weekend.
Comment #19
Wim Leers#18 is looking excellent already! 👏
Comment #20
wannesdrI'm going to have a shot at this test.
Comment #21
wannesdrI made a new patch where I restructured and split up the tests. Test dataproviders are all prefixed with 'provider'.
Some were too unique to put together with the rest so I created separate methods for them. If in the future they also need a dataprovider we can add them when necessary.
In my opinion: figcaption tests also deserve more attention so I inserted a placeholder for them already. They need to be moved from other tests, or created from scratch maybe.
Comment #22
wannesdrComment #23
Wim LeersHere is interim feedback, this is heading the right direction — thanks!
Nit: Already in the class doc, can be removed :)
Nit: We don't add
@throws
in test methods :)Nit:
$embed_attributes
is an array, so should be typehintedarray
.Nit:
$this->webUser
can be a local variable, it's not reused anywhere.The naming confused me; I think
$is_published
and$allowed_to_view_unpublished
are clearer.These test case-specific
not_contains
cases are already tested automatically/generically, so there's no need to repeat them here.Nit: the leading
\
is unnecessary.Übernit:
\'
in there: you could use either backticks or wrap it in double quotes.This is in
::testInvalidEntity()
and is extremely similar to the above test method. Perhaps a helper method would simplify this. Or perhaps one of thetest*()
methods can call the other?Why is there a parameter if this is not a data provider?
Outdated annotation :)
What is this asserting? How can it be not empty?
Comment #24
wannesdrPatch (should) now apply.
Will fix feedback from Wim in the next patch.
Comment #25
wannesdrUpdate with the fixed feedback of Wim.
I will continue with refactoring later this morning.
Comment #26
Wim LeersAWESOME! Tests still passing with this commented out. So let's remove it now :)
Perhaps it'd be clearer to not use
<not-drupal-entity>
but$this->randomMachineName()
? :)This is actually fairly confusing. Because we allow
NULL
orarray
, not only are the test cases more difficult to grok ("what is the meaning ofNULL
here?"), it also makes for more complex assertion logic. The assertion logic first needs to check the type of the argument, whereas if it'd just always bearray
, we could do this:That'd be it!
In the test cases, we'd then have
[]
instead ofNULL
, which is more clear: there are no strings whose non-existence needs to be asserted.How is this going? :)
Comment #27
wannesdrInbetween update of the patch.
I move the filterTranslations to a different test entirely and refactored it to use one dataProvider.
I also further refactored the filterTests.
What definitely needs to be done next is check which methods in the EntityEmbedTestBase are unique or shared between EntityEmbedFilterTest and EntityEmbedFilterTranslationTest and move them accordingly. And also cleanup obsolete code in any of those three classes.
To be continued...
Comment #29
wannesdrI fixed the issue that made the test fail. I changed the testInvalidEntity dataProvider so the $contains and $not_contains are also arrays.
Comment #31
wannesdrI forgot to re-add the TranslatableInterface RenderContext use statements ofter they moved around a bit.
Comment #32
wannesdrFixed the patch. Helper functions moved to the right class and cleaned some of the CS warnings in de test run.
Comment #34
wannesdrFixed the testContainerTagElementReplace to use randomMachineName().
Comment #36
wannesdrApparently the randomMachineName() generator also uses capital letters, this is not allowed for a tag and therefore the test fails.
I'm going to replace the randomMachineName() with just a hardcoded string.
Also: https://www.drupal.org/project/drupal/issues/2571183, so since this may be deleted once it's a good thing not to use it in our test.
Thanks to @borisson_ for the issue nr.
Comment #37
wannesdrNew patch to remove the randomMachineName() from comment #36.
Comment #38
wannesdrYay! Finally green test results!
Here is a new patch with the final coding standards messages fixed.
Comment #39
borisson_Nitpicks ahead.
Service doesn't have to be capitalized here.
Unneeded blank line.
Helper functions don't need to be public - can be protected.
This has a dataProvider, but only one value in the dataprovider. I don't think it's needed to already use the dataprovider if it doesn't gain anything of value.
These can be removed, I think?
^
this is missing words? a "because" after the comma would make this more readable.
Comment #40
wannesdrThanks @borisson_ for the feedback!
Attached is a new patch with the corrections. I made all the helper functions protected and also moved one to the bottom of the EntityEmbedFilterTest, seemed better that way.
Comment #41
Wim LeersBeen caught up in meetings all day. Reviewed & committed two CKEditor-related patches today; this is my top priority for tomorrow 🥳
Comment #42
oknateGreat!
I can think of some edge cases to add after the last round of bug fixes.
Perhaps it's redundant, but we could also test the alt and title overrides here.
Comment #43
Wim LeersInterestingly, I have some fails locally, with PHP 7.2.14:
This is caused by
>firstChild
returning a "text" DOM node for whitespace.I wonder if this is specific to PHP 7.2, so I queued a test for it: https://www.drupal.org/pift-ci-job/1324414. That passed too. So … I don't know what's going on here, but let's just work around the problem by making the test coverage more robust :)
Comment #44
oknateI believe DOMNode doesn't have getAttribute but inherits it from DOMElement, the problem is it not every DOMNode is a DOMElement, so we'd need to check if it is. Why the test fails locally, I don't know.
Comment #45
oknateThis task is getting pretty large and unfocused. Perhaps we should commit an intermediary first step and create follow ups for
1) Converting to Kernel test
2) Specific edge cases.
Or just commit an intermediary step for the progress so far and leave this issue open.
Comment #46
oknateWhen I say "unfocused", specifically I refer to this:
This could go for a long time. So I think it would be great to get the progress so far committed, and then we continue with this.
Comment #47
Wim LeersActually, to make iterating on this faster, I spent a few hours today on making this a kernel test. The additional set of changes is minimal. It's mostly in
::setUp()
. Which means it's much easier to review and understand than all of the work that has happened on this issue so far.The difference is quite big:
Next up: extracting common logic in a base test class for all filter kernel tests. And then actually reviewing the changes.
In converting this to kernel tests, a few assumptions in the functional tests were made more explicit, which is an expected and welcome consequence 🙂
Comment #48
oknateWow, nicely done. I'm looking forward to reviewing how you did it. I tried a few weeks ago and I got stuck.
Comment #49
Wim LeersBefore extracting a base test class: moving to the right location.
Comment #50
oknate1) Missing space before docblock.
2) For drupalCreateNode, can we use one array, as we do in other tests?
3) Why no param descriptions? The coder linter didn't flag them either. Are they optional for tests? As they are self-describing, I don't think we need them, if it's not a coding standard violation.
4) no param descriptions for testInvalidEntity() too? See #3.
5) This text:
Is a bit confusing. Perhaps "Test HTML tag with same attributes as drupal-entity not affected."
6) in testOverridesAndRenderCaching() we create a media entity. Maybe this should be moved to setUp() so it can be reused.
7) I'm not a fan of this function:
I think it's not readable and self-describing, I think it should be two functions, assertContainsMultiple() and assertNotContainsMultiple().
Comment #51
oknateChanged #1, #2 and #5. If I get a chance tonight, I'll look at #7.
Comment #53
oknateFixes missing period.
Comment #54
oknateReplacing assertContainsHelper() with assertContainsMultiple() and assertNotContainsMultiple(). Purely cosmetic. I just think it's easier to read this way.
Comment #55
oknateDropping the word "hopefully" from title in reference to Kernel test conversion. Nicely done, Wim.
Comment #56
oknateAdding base class EntityEmbedKernelTestBase.php and updating EntityEmbedFilterTranslationTest and EntityEmbedFilterTest to extend it.
Comment #57
oknateComment #58
oknateComment #60
oknateI guess that admin user was used after all. PHP storm was indicating it as an unused variable.
Comment #61
Wim LeersThis then extracts a base class doing the absolute minimum. We don't want the base test class to be coupled to all the potential things we want to have tests for; we want each subclass to install the additional modules needed and set up the additional configuration needed. That way, it remains very clear what the dependencies are, and adding new capabilities then also is forced to provide correspondingly clear test coverage.
EDIT: oh wow, @oknate continued working on this too. My bad, I should've assigned to myself. No big deal though — I'll incorporate his changes :) That means only #56 will largely be wasted. Assigning to myself, as I should've done before.
To be crystal clear: the attached interdiff is relative to my last patch (#48).
Comment #62
Wim Leersinterdiff-ported-51_and_53.txt
.interdiff-ported-54.txt
. Also: 👏👏 — that's exactly what I was going to suggest to @Wannes DR in a next iteration :)\Drupal\user\Entity\User::hasPermission()
🤓Comment #63
Wim LeersThe current test coverage is specifically testing Classy's markup and its subthemes. We shouldn't do that.
(It is currently not assuming
core/modules/filter/templates/filter-caption.html.twig
butcore/themes/classy/templates/content-edit/filter-caption.html.twig
.)Comment #64
Wim LeersThis test refactor is currently leading us into a kinda awkward place. We're not testing
@Filter=entity_embed
in isolation: we're testing it together with@Filter=filter_caption
. Ideally we'd test it in isolation. ButIn HEAD:
In this patch, that is converted to:
This is asserting the results for
@Filter=filter_caption
, but not for@Filter=filter_align
. Having integration tests makes sense.Note that this also lost the test coverage that asserts whether the
alt
andtitle
on<drupal-entity>
have been persisted onto the generated<img>
tag. And it in fact is not testing anything on the<img>
tag at all anymore, whichgit blame
shows was the goal in #2712111: Embed specific attributes are cached along with the entity, where this test coverage was originally added.I also have my doubts about whether this is truly clearer. I wrote in #5 how I like that you're taking it further, but it never was taken all the way, and hence is currently resulting in a net reduction in test coverage. This particular bit of test coverage was lost in #7's interdiff.
I'll continue to evaluate this as I review the rest of the patch.
Comment #65
Wim LeersHere is another concrete example of where the conversion is wrong:
\Drupal\Tests\entity_embed\Kernel\EntityEmbedFilterTest::testDisplayPluginPreference()
. This is porting the test coverage added by https://git.drupalcode.org/project/entity_embed/commit/b9a4f65c88b75cf3d.... It's asserting the presence of data- attributes continuing to exist that we set ourselves (which is pointless, of course they continue to exist), and is testing caption filter integration (which is not the edge case this is aiming to test). Reducing this back to the original scope make this much clearer.Comment #66
Wim LeersAnd another such example:
testEmbedSettingsCompatibility()
. This used to and still should be testing that no<a>
was created, since that's what the legacydata-embed-settings
attribute is specifying. But that's not being asserted at all anymore.(This was introduced by #2760801: Rename data-entity-embed-settings attribute — see https://git.drupalcode.org/project/entity_embed/commit/72a93e2d5efa7a760....)
Comment #67
Wim LeersThese
$this->assertNotContains('This placeholder should not be rendered.', $output);
assertions all over the place were annoying, distracting and confusing in HEAD, and they still are. Let's make that better.Comment #68
oknateExcellent finds in #64, #65 and #66. That's the danger with changing lots of things at once. Some things tend to get lost and overlooked in the shuffle. Thanks for double checking these still do what they were originally intended to do!
Comment #71
Wim Leers#68: indeed! An unavoidable painful process to go through when taking code with a lot of history but without clear test coverage. None of this is a criticism on either you or the original code contributors — we're all bound to deadlines, we all learn along the way, we all would like to do better. I just am fortunate enough to be given the task to bring this to core and have gone through stabilization processes like this many times before :) Please continue to double-check what I'm doing, and let me know when you disagree (or when you're happy with a change!).
Comment #72
Wim LeersLooks like there was a PHP 7.2-specific assertion.
Comment #73
oknateI’ll double check the progress later today. I had to fix an issue for another project this morning.
Comment #74
Wim LeersJust like #65 and #66, here's another correction, this time for
testAttributesWhenUsingImageFormatter()
. This is the one I was talking about at length in #64.Comment #75
Wim LeersLet's remove the dependency of our kernel test on
entity_embed_test
, which installs boatloads of configuration, so it's not at all clear what exactly we're testing with.(
entity_embed_test
sort of became a dumping ground, which was fine for fast iteration, but if we want to bring this to core, we'll need more rigor.)Comment #76
Wim Leers#75 allows us to remove
editor
andckeditor
from the modules being installed. We're getting to a place where dependencies are actually clear! 🥳Comment #77
Wim LeersRelated to #74: the cacheability-related assertions in #2712111: Embed specific attributes are cached along with the entity are actually covered much better by #3058872: Entity Embed render array shouldn't cache separately from host field, which introduced
testOverridesAndRenderCaching()
.That being said,
testAttributesWhenUsingImageFormatter()
is still valuable to keep: it asserts that overrides are working forFile
entities plus@EntityEmbedDisplay=image:image
, whereastestOverridesAndRenderCaching()
is testingMedia
entities plus@EntityEmbedDisplay=view_mode:*
.I think it makes sense to test both of those "override data of the embedded entity" scenarios in a single test class. #75 was a necessary step to make that feasible, because we don't want to be changing test logic and moving in a single interdiff, that makes it much to hard to track.
So this interdiff moves the two aforementioned test methods to a new
\Drupal\Tests\entity_embed\Kernel\EntityEmbedFilterOverridesTest
class, renames the methods and improves their docs, but doesn't change anything about their code. A happy (and very much intentional) consequence is that thefile
,image
andmedia
modules no longer need to be installed forEntityEmbedFilterTest
, and almost no configuration needs to be installed anymore! 💪 That means that just like the name indicates, this is now providing the foundational tests only, without testing integration with lots of other modules, entity types, and whatnot.Simultaneously, I've moved
assertHasAttributes()
anddrupalCreateRole()
into the base class, because there are now multiple test classes using them.Comment #78
Wim LeersThe changes made to this test class are now irrelevant. Let's simply drop those hunks from the patch.
Comment #79
Wim LeersHaving looked at the override tests in detail for #77, I spotted a few problems:
drupalCreateNode()
Fixed all.
Comment #80
Wim LeersAnd another problem in that same test, but which I wanted to post separately to keep scope clear: in one of the two test methods, we're using the existing trait, but wrapping it in a helper of our own. In the other test method, we're copying an existing file in core. We should make this consistent and less complex.
Comment #81
Wim LeersI spotted
$this->assertNotContains('drupal-entity data-entity-type="node" data-entity', $output);
in a few places, this should be merged intoassertEntityEmbedFilterHasRun()
. That assertion method was added in #67 and this addition makes it much more clear what it does. It also helps that we're now consistently asserting this, instead of only in two places — that made it extra confusing!Comment #82
Wim LeersAn assortment of clarity nitpicks:
data-align
anddata-caption
where they're not needed$rendered_embed = $xpath->query('//div[contains(@class, "embedded-entity")]')
where that is not the rendered embed, but the container of the rendered embed — renamed all of them toembedded_entity_container
With these changes, I consider
\Drupal\Tests\entity_embed\Kernel\EntityEmbedFilterOverridesTest
core-worthy now.Comment #83
Wim LeersI'll continue iterating on
EntityEmbedFilterTest
because that definitely still needs more love. But I'm approaching my end of day. @oknate or @Wannes, feel free to port the@Filter=filter_caption
and@Filter=filter_align
test coverage from before that is currently missing. ThetestFigCaption()
placeholder that Wannes added would be a great place to start to see those appear in :)Comment #84
oknateAwesome progress, I'll take a look later today. When talking about moving into core, the plan isn't to move the entity embed filter into core, but a close cousin of it just for media, right? Is the plan then to have the entity embed filter extend that? Or to have them both extend a base filter?
Comment #85
Wim LeersI started working on this again. Started the process of comparing the old test coverage with the refactored test coverage, to ensure we don't lose any coverage.
Comment #86
Wim LeersUpdating
testMissingEntityPlaceholder()
to not create its own node but reuse the existing one, and to maximally useassertHasAttributes()
rather than using that and doing raw string presence assertions.Comment #87
Wim LeersThere is a lot of repetition of a few lines of code. Let's introduce a helpful helper and let it absorb
assertEntityEmbedFilterHasRun()
:Comment #88
oknateNice idea in #87!
Was this meant to go in?
It looks like it might be reverting part of #67.
Actually, it looks like the comment is new. So nevermind.
Comment #89
Wim Leers#88: yep, that's just a new comment and adding one assertion to be more explicit about what it's testing. That's the only case that cannot be converted precisely because it is not testing
<drupal-entity>
:)If you liked #87, I think you'll like this too :)
We have a lot of parsing all over the place. So much of this:
But
\Drupal\KernelTests\AssertContentTrait
is alreadyuse
d byKernelTestBase
, so usingcssSelect()
is within reach!This means
assertHasAttributes()
has to change slightly, becauseAssertContentTrait
unfortunately usesSimpleXML
for parsing, notDOMDocument
. But I think that's okay. This again makes the tests simpler to understand.Comment #90
Wim LeersFixed a few nits, plus:
As of #81, this is handled automatically by
applyFilter()
.Rather than asserting the absence of this content, it's better to assert the absence of the placeholder element, because further in the test case we assert the presence of that placeholder element (after deleting the embedded entity).
Comment #91
oknateRe #89, that's a lot less verbose!
Nice refactor . I don't know this cssSelect I'll take a look.
Comment #92
Wim Leers#87 updated almost everything, with the exception of
EntityEmbedFilterTranslationTest::testFilterTranslations()
Let's update that too.Comment #93
Wim LeersSo #92 did quite a bit of this:
That pattern of swapping
assertContains()
forassertRaw()
can be done in more places. And when that's done,applyFilter()
no longer needs to return the resulting string.This does that.
Comment #94
oknateCool, I didn't know you could do this:
+ $this->setRawContent($output);
It looks like this is Kernel test specific.
Comment #95
Wim Leers#94: That's from
\Drupal\KernelTests\AssertContentTrait
.Following up on #92: #27 introduced
$assert_title_from_source, $assert_title_lang, $assert_extra
and friends, and I think @Wannes DR perhaps thought it's more complicated than it is — this can be simplified a lot :)Comment #96
Wim LeersI've also finished comparing the test coverage with this patch applied compared to HEAD's test coverage. Nothing is missing except for the implicit integration test coverage with the
@Filter=filter_align
and@Filter=filter_caption
filters. Hurray! 🥳Thanks to both @oknate and @Wannes DR, I was able to approach this was a fresher perspective than I otherwise would have. Both of your suggestions, ideas and contributions are still present and will continue to live on. Hopefully you've both appreciated my taking the time to post piece-by-piece improvements. I am still all ears to hear suggestions from you too 🙂
I will continue working on those in a few hours.
Comment #97
borisson_I am super happy about this approach, I've learned a lot by watching you break up all these changes into logical units. Thank you! 👍
Comment #98
oknateI totally appreciate the play-by-play. I've learned quite a bit too. I also have learned sometimes it's better to post three patches with three groups of changes rather than to "save space" on the issue. It makes it much easier to explain your changes.
Comment #99
Wim Leers#97: That's wonderful to hear :) Made my day — thanks! 🥳🤓
One of the crucial things that are still missing (and are also missing from HEAD) is asserting the presence of the expected bubbleable metadata. The additional assertions are trivial, but the code to properly run filters and collect bubbleable metadata (cacheability & attachments) is not.
Comment #100
Wim LeersWhat I didn't tell you in #99 is that this also happens to be the infrastructure I need to be able to add caption filter integration tests 🤫😇
This test is pretty rough, with lots of copy/pasted bits, but they'll soon evaporate! 🌞
Comment #101
Wim LeersThree different calls, because three different needs. That's pretty awkward.
Fortunately #99 gave us the infrastructure to make this better 🥳
Comment #102
Wim LeersThis hunk shouldn't have been in there, that's for a future iteration…
Comment #103
Wim LeersPart 1 of #102's promised evaporation delivered.
Comment #104
Wim Leers$this->renderer
which is pointless as of a few patches ago.Comment #105
Wim LeersPart 2 of #102's promised evaporation delivered.
Now we have integration test coverage for
filter_align
,filter_caption
and both simultaneously. 👍Comment #107
Wim Leersdata-entity-id
is deprecated, but the tests would make you think otherwise. This is a problem for future maintenance.(Part of this already snuck in #105 and hence the failure.)
Comment #108
Wim LeersIt's very late. Time to wrap up my day. I'll continue tomorrow and expect to be able to commit this tomorrow afternoon my time.
(There is still some test refactoring that I think needs to happen. But the end is near!)
Added missing tests I'm aware of to the issue summary.
#42:
data-entity-id
, I actually just did that 😀Finally,data-view-mode
definitely is not deprecated. Why did you think that?Comment #109
Wim LeersIf anybody wants to work on this in the mean time, feel free to. I'll continue in ~9 hours.
Comment #110
oknateThanks, Wim. Today was epic. I'll review if possible tonight!
Comment #111
Wim LeersSpent most of my morning on #3038254-62: Delegate media library access to the "thing" that opened the library, but now back on this!
Comment #112
Wim LeersSimplified
EntityEmbedFilterTranslationTest::testFilterTranslations()
— most of the embed attributes are the same across all test cases, so there's no need to repeat them many times, because then it's no longer clear what exactly we're testing (what input is changing and whose effect we're asserting).Comment #113
Wim Leers#112 was a fine improvement, but while working on it I spotted a problem that I apparently gradually introduced and made worse: in #87 I stopped passing the
$process_lang
input to the filtering. This should have broken tests, but did not, because the assertions were wrong.Then in #95, I made that worse, by removing the
$process_lang
parameter altogether, since it seemed to have no effect. Well, it did not have any effect, otherwise #87 would've failed, but in doing so we lost about half of what we're testing!I only found this thanks to simplifying (in #112) and then writing corresponding clear test case labels. This makes it easier to understand, but also helps spotting mistakes, as I've just proven :D
Comment #114
Wim LeersA cohesive single test method and data provider are now within reach. 🥳
The end result after these last few iterations is complete test coverage (better than in HEAD!) and easier to understand tests.
Comment #115
Wim LeersAnd finally, cacheability assertions (only the relevant one: "does this trigger variations or not?") and some clean-up. I now consider
EntityEmbedFilterTranslationTest
to be core-worthy, just like I consideredEntityEmbedFilterOverridesTest
core-worthy since #82.Comment #116
Wim LeersWe lost the test coverage that ensures that cacheability of entity access is bubbled up, which I helped write nearly three years ago: #2593379: Analyze/improve/fix handling of bubbleable metadata in entity_embed 😲
(Also, thanks to the refactored tests it's now very easy to observe the impact!)
Comment #117
Wim LeersRound of clean-up. Fixes nits. Fixes coding standards violations. Removes the now unnecessary
loadEntityByAttributes()
helper.Comment #118
Wim LeersThe accidental inclusion of a hunk mentioned in #102 is now actually intentional :)
Comment #119
Wim LeersproviderTestFilter()
test cases.testEntityEmbedDisplayDefaultBackwardsCompatibility()
.testContainerTagElementReplace()
and simplified it a lot.Comment #120
Wim LeersMoved all
@group legacy
tests to a new\Drupal\Tests\entity_embed\Kernel\EntityEmbedFilterLegacyTest
. That represents test coverage that is 100% technical debt in the filter.Comment #121
Wim LeersThe idea behind
not_contains
was good, but turns out we have no uses for it, at least not anymore, after all other refactoring. So let's remove it.Comment #122
Wim LeersSimilarly,
contains
was a good idea. But now it's only being used for one kind of thing (many times):That's the value of the body field of the sample entity used for embedding. Put differently: it's asserting that the embedded entity is actually rendered.
Rather than a highly abstract "contains nothing" (when the entity is inaccessible) or "contains this particular string" (when it is accessible and hence rendered), let's make that more clear.
While doing this, I also made this change:
The deleted line hardcoded knowledge about the expected behavior, rather than it merely asserting what it is being told to assert. Easily introduced, hard to realize why a test is complex :)
Comment #123
Wim LeersMore than half of the complexity of
testFilter()
(at least in terms of function arguments and hence information per test case in the provider) is for the "access allowed or denied" test cases.That's a strong indicator that should be extracted to its own test method plus data provider; that should make things a lot simpler.
Comment #124
Wim Leers#123 renamed
testFilter()
totestBasics()
. Time to review that one last time.data-entity-embed-display + data-view-mode ⇒ data-entity-embed-display wins
test case in thetestBasics()
data provider meanstestEntityEmbedDisplayAttributeVersusViewModeAttribute()
is a mere duplicate, so we can remove it.data-entity-uuid + data-entity-embed-display
full
not existing and then core automatically falling back todefault
. We should test that too.Addressed all those points.
Comment #125
Wim Leers#124 introduced a much more reliable way of asserting that the embedded entity was rendered.
To resist the temptation to again start asserting based on the body text, I'm removing the body text altogether 🤘 And in doing so, there's one less cache tag associated, which is another nice simplification. (This is because no text format ID was specified and hence it had to resolve the fallback format by reading configuration.)
Comment #126
Wim Leers#124 said it'd remove
testEntityEmbedDisplayAttributeVersusViewModeAttribute()
, but I apparently failed to do so 😅Done now, and fixed most of the coding standards violations and some nits.
Comment #127
Wim LeersThis is a remnant from an experiment. Oops.
Comment #128
Wim LeersThe final bit of clean-up:
testInvalidEntity()
was not testing anything. But its data provider showed the right intent. OTOH, the assertions would be 99% identical to those intestMissingEntityPlaceholder()
. So let's merge them.Comment #129
Wim LeersUpdated issue summary to reflect current status.
One key thing is still missing:
. Other than that, I just need to have one last pass throughEntityEmbedFilterTest
.Comment #130
Wim LeersSo: recursive embed test coverage. Let's start.
\Drupal\entity_embed\Exception\RecursiveRenderingException
was last touched >3.5 years ago. By a commit that says it's about something else. Without an issue. Apparently that commit moved it from\Drupal\entity_embed\RecursiveRenderingException
.Removed dependency on entity_reference.
— because apparently this is not a problem that Entity Embed encountered, it's one that it learned to protect against from the Entity Reference module and its field formatter. Again without issue. The class contained a more useful comment at that time:… but despite that seemingly pointing to something Entity Embed-specific, it seems to have its roots in the Entity Reference module still.
48763795 Dave Reid <dave@davereid.net> on 2014-04-18
! Clearly, Dave knew about this recursive rendering thing being a problem, probably from his vast experience with Drupal and seemingly having run into complex problems with entity reference field formatters :) The "without an issue" remarks are not meant as snark, but as factual observations that explain why it's hard to figure out the how and why of this and hence how to test this!So, let's look at the Entity Reference module. It used to contain
Drupal\entity_reference\RecursiveRenderingException
. Also in Drupal 8 core. Not anymore though. #2404021: entity_reference formatters should be in Core removed it: rather than throwing an exception, it now just logs an error, because that avoids a broken site. And #2073753: Fix and add tests for the recursive rendering protection of the 'Rendered entity' formatter added test coverage for this, more than a year later, and it hasn't been touched since:\Drupal\Tests\field\Kernel\EntityReference\EntityReferenceFormatterTest::testEntityFormatterRecursiveRendering()
— yay!Ironically (and thankfully!) this led me to realize that Entity Embed's recursion protection is currently broken, for the same reasons
EntityReferenceEntityFormatter
's was broken: see #2073753: Fix and add tests for the recursive rendering protection of the 'Rendered entity' formatter. But that means I'd have to start violating an important principle of this issue: test coverage changes only, no code changes!So created #3063398: Update EntityEmbedFilter's recursion protection to match EntityReferenceEntityFormatter's and add test coverage for that.
Comment #131
Wim LeersPer #130, we're now in the very final stages.
Time to fix the remaining five coding standards violations. Done.
Comment #132
Wim LeersLast but not least: some moving around of methods and code blocks for improved clarity. And a few statements that could still be simplified. Now down to zero
$this->assertRaw()
calls too :)Comment #133
Wim LeersWent for a run to think about it once more — I still think this is ready 🥳
Comment #135
Wim Leers🚢
Comment #136
oknateIn regards to this:
This has no functional affect, it just allows you to easily test the correct view mode is being used on render? That's cool.
Comment #137
oknateI read through the commit. Fantastic stuff. I wish I could have kept up with you on all of it over the last two days. Lots of stuff in there for me for reference on future tests. Thanks for all your hard work on this this week.
Comment #138
Wim Leers#136: correct!
#137: Thank you too! You've been instrumental in helping get Entity Embed to where it is today. In particular, without you, we wouldn't have nearly the JavaScript test coverage we do!
Comment #139
oknateThanks. I'm still not clear how much of this module might move into core. Is it just the filter?