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

FixtureFactory does not apply data relations correctly #180

Open
raissanorth opened this issue Aug 8, 2018 · 7 comments
Open

FixtureFactory does not apply data relations correctly #180

raissanorth opened this issue Aug 8, 2018 · 7 comments

Comments

@raissanorth
Copy link

I am trying to add an ElementalPageExtension to Page via the ConfigContext.

It appears that the FixtureFactory is not saving the relations correctly. At the time of object creation the extension is not applied. If we add the extension manually before creating the object it almost works, but we have to query the database directly, so that the relation gets saved correctly in the database.

I have in my feature file: Given I have a config file "enable-elemental.yml".
The yml file has this content:

---
Name: testonly-enable-elemental
---
Page:
  extensions:
    - DNADesign\Elemental\Extensions\ElementalPageExtension

I have added some fixture context like:

/**
* Create a page containing an ElementalArea and an Element
* Example: Given a "Blocks Page" "page" has a "Block Title" content element with "Sample content" content
*
* @Given the :pageTitle :type has a :elementTitle content element with :elementContent content
*
* @param string $pageTitle
* @param string $type
* @param string $elementTitle
* @param string $elementContent
*/
public function theHasAContentElementWithContent($pageTitle, $type, $elementTitle, $elementContent)
{
    $targetClass = $this->convertTypeToClass($type);
    $targetObj = $this->getFixtureFactory()->createObject($targetClass, $pageTitle);
    $area = $targetObj->ElementalArea()
    // Throws exception "method ElementalArea does not exist"! But the extension should add it?

    // Add blocks to elemental area for testing...
}

After adding $targetClass::add_extension(ElementalPageExtension::class); before the fixture factory call, the fixture context works and we can add elements but when the elemental area loads on the page during the behat test it has got a new elemental area?!

We can resolve this by directly querying the database to actually map the relation correctly eg:

DB::query("INSERT INTO Page (ID, ElementalAreaID) VALUES ($targetObj->ID, $targetObj->ElementalAreaID)");

However this does not feel like it's working correctly at all.

@tractorcow
Copy link

Can you add another Given I visit "dev/build?flush=1" (or similar step) after setting the config, but prior to setting up the fixture rows? maybe that will fix it.

@ScopeyNZ
Copy link

ScopeyNZ commented Aug 8, 2018

Hey @tractorcow. Raissa had that in the feature. Forgot to mention that!

It's also interesting that without any hacks like ::addExtension the extension just does not exist in the fixture context part, but the pages have elemental areas during the rest of the Behat test.

@tractorcow
Copy link

Oh right, it won't work because you need to add the extension to the context of the CLI process running behat, not the web process getting flushed.

In that case, you may need yet another behat fixture for and I add an extension "" to "" class, which occurs in the CLI context. sorry!

@ScopeyNZ
Copy link

ScopeyNZ commented Aug 8, 2018

That feels like something we could PR into this repo? We'll test if it works first.

@robbieaverill
Copy link

New fixture step for and I add an extension... works

@ScopeyNZ
Copy link

There's a bit of scaffolding required for this:

  • Create a config file
  • Use the step "I have config file..."
  • Step "visit dev/build?flush"
  • Custom step "and I add an extension"

I think we should add a step to this repo that does all that automatically, then we don't have the weird double up of a config file and the custom step so the CLI context knows what's going on. Thoughts?

Additionally - is there a way we can avoid the dev/build if we know specifically we are adding this one extension? Adds a lot of time to each scenario.

@raissanorth
Copy link
Author

We're going to change the background to be a list of UI steps to create elements rather than use a fixture factory.

We've tried to use the fixture factory to create a Page -> has_one -> ElementalArea (created onBeforeWrite in Page) -> has_many -> ElementContent assigned to the ElementalArea. When placing a breakpoint after this fixture definition and inspecting the database we see the relationship is all set up correctly, however when the Behat test runs the page edit form the following logic executes:

# File: ElementalAreasExtension::updateCMSFields
// Example: $eaRelationship = 'ElementalArea';
$area = $this->owner->$eaRelationship();

// if area isn't in the database then force a write so the blocks have a parent ID.
if (!$area->isInDb()) {
    $area->write();

    $this->owner->{$key} = $area->ID;
    $this->owner->write();
}

This creates a new ElementalArea with ID 7 (instead of ID 6 from fixture factory as we previously checked) and assigns that to the page instead, meaning when the list of elements loads it has nothing in it because the fixtured ElementContent belongs to ElementalArea with ID 6, not 7.

It seems like there's a disconnect between states in the fixture factory and the actual UI during the Behat test. Perhaps cache/config etc... we give up and use UI step definitions in the background instead of fixture context definitions.

For reference, here's the definition we were trying:

/**
 * Create a page cothe "Blocks Page" :type has a "Block Title" content element with "Sample content" content
 *
 * @Given the :pageTitle :type has a :elementTitle content element with :elementContent content
 *
 * @param string $pageTitle
 * @param string $type
 * @param string $elementTitle
 * @param string $elementContent
 */
public function theHasAContentElementWithContent($pageTitle, $type, $elementTitle, $elementContent)
{
    // Create the page (ElementalArea is created on write and attached to it)
    $targetClass = $this->convertTypeToClass($type);

    $page = $this->getFixtureFactory()->get($targetClass, $pageTitle);
    if (!$page) {
        $page = $this->getFixtureFactory()->createObject($targetClass, $pageTitle);
    }
    // Ensure that an ElementalArea is created (see ElementalAreasExtension)
    $page->write();

    // Create the element and assign it to the page's ElementalArea
    $element = $this->getFixtureFactory()->createObject(ElementContent::class, $elementTitle);
    $element->ParentID = $page->ElementalAreaID;
    $element->Content = $elementContent;
    $element->write();

    $page->ElementalArea()->write();
}

Example step:

And the "Blocks Page" "page" has a "Block Title" content element with "Sample content" content

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants