Cms: Using fixtures and amOnPage methods in a functional test returns a 404

Created on 1 Jul 2019  ·  9Comments  ·  Source: craftcms/cms

Description

I have two working functional tests:

<?php

use craft\elements\Entry;

class NewsCest
{
    public function landingPageExists(FunctionalTester $I)
    {
        $I->amOnPage("/news");
        $I->seeResponseCodeIs(200);
    }

    public function welcomesUsers(FunctionalTester $I)
    {
        $I->amOnPage("/news");
        $I->see("News Articles", "h1");
    }
}

Here's the full command line output when I run Codeception:

❯ php vendor/bin/codecept run functional tests/functional/NewsCest.php
Codeception PHP Testing Framework v3.0.2
Powered by PHPUnit 6.5.14 by Sebastian Bergmann and contributors.
Running with seed: 


Functional Tests (2) --------------------------------------------------------------------------------------------------------
✔ NewsCest: Landing page exists (0.10s)
✔ NewsCest: Welcomes users (0.03s)
-----------------------------------------------------------------------------------------------------------------------------


Time: 8.54 seconds, Memory: 32.00MB

OK (2 tests, 2 assertions)

However, if I add _fixtures() to this I begin to receive 404 errors for these same tests:

<?php

use craft\elements\Entry;
use myprojecttests\fixtures\EntryFixture;

class NewsCest
{
    public function _fixtures(): array
    {
        return [
            'entries' => [
                'class' => EntryFixture::class
            ]
        ];
    }

    public function landingPageExists(FunctionalTester $I)
    {
        $I->amOnPage("/news");
        $I->seeResponseCodeIs(200);
    }

    public function welcomesUsers(FunctionalTester $I)
    {
        $I->amOnPage("/news");
        $I->see("News Articles", "h1");
    }
}

My command line output:

❯ php vendor/bin/codecept run functional tests/functional/NewsCest.php
Codeception PHP Testing Framework v3.0.2
Powered by PHPUnit 6.5.14 by Sebastian Bergmann and contributors.
Running with seed: 


Functional Tests (2) --------------------------------------------------------------------------------------------------------
✖ NewsCest: Landing page exists (0.04s)
✖ NewsCest: Welcomes users (0.02s)
-----------------------------------------------------------------------------------------------------------------------------


Time: 8.36 seconds, Memory: 32.00MB

There were 2 failures:

---------
1) NewsCest: Landing page exists
 Test  tests/functional/NewsCest.php:landingPageExists
 Step  See response code is 200
 Fail  Expected HTTP Status Code: 200 (OK). Actual Status Code: 404 (Not Found)
Failed asserting that 404 matches expected 200.

Scenario Steps:

 2. $I->seeResponseCodeIs(200) at tests/functional/NewsCest.php:20
 1. $I->amOnPage("/news") at tests/functional/NewsCest.php:19

Artifacts:

Response: MY_SITE/tests/_output/NewsCest.landingPageExists.fail.html

---------
2) NewsCest: Welcomes users
 Test  tests/functional/NewsCest.php:welcomesUsers
 Step  See "News Articles","h1"
 Fail  Element located either by name, CSS or XPath element with 'h1' was not found.

Scenario Steps:

 2. $I->see("News Articles","h1") at tests/functional/NewsCest.php:26
 1. $I->amOnPage("/news") at tests/functional/NewsCest.php:25

Artifacts:

Response: MY_SITE/tests/_output/NewsCest.welcomesUsers.fail.html

FAILURES!
Tests: 2, Assertions: 2, Failures: 2.

Fixture file path

- tests/
    - fixtures/
        - data/
            entries.php
        EntryFixture.php

fixtures/EntryFixture.php

<?php

namespace myprojecttests\fixtures;

use craft\test\fixtures\elements\EntryFixture as BaseEntriesFixture;

class EntryFixture extends BaseEntriesFixture
{
    /**
     * @inheritdoc
     */
    public $dataFile = __DIR__ . '/data/entries.php';
}

fixtures/data/entries.php

<?php

return [
    [
        'sectionId' => $this->sectionIds['news'],
        'typeId' => $this->typeIds['news']['news'],
        'title' => 'News Article',
    ],
];

Not sure why that is, but figured I'd reach out in case it's an RC2 bug! 😃

Additional info

  • Craft version: RC2
  • PHP version: 7.2.12
  • Database driver & version: MySQL 5.7.24

All 9 comments

@aaronbushnell Hmm, strange...

Can you share the codeception.yml and functional.suite.yml files to try and reproduce this? Thanks!

Absolutely! Here ya go, @gtettelaar:

codeception.yml

actor: Tester
paths:
  tests: tests
  log: tests/_output
  data: tests/_data
  support: tests/_support
  envs: tests/_envs
settings:
  bootstrap: _bootstrap.php
params:
  - tests/.env
modules:
  config:
    \craft\test\Craft:
      configFile: 'tests/_craft/config/test.php'
      entryUrl: 'http://MY_REDACTED_DOMAIN.test/index.php'
      projectConfig: {file: 'config/project.yaml'}
      migrations: []
      plugins: []
      cleanup: true
      transaction: true
      dbSetup: {clean: true, setupCraft: true}

functional.suite.yml

class_name: FunctionalTester
modules:
  enabled:
    - \craft\test\Craft
    - \Helper\Functional

@aaronbushnell Looks like you are using the Project config option aswell.

Is it possible to share your config/project.yml file here? If not can you send it to [email protected] with this ticket number?

Absolutely!

dateModified: 1561917672
email:
  fromEmail: [email protected]
  fromName: 'Tmi Heroku Craft'
  transportType: craft\mail\transportadapters\Sendmail
fieldGroups:
  be00446b-966b-45a7-87ca-825ec46f6c22:
    name: Common
fields:
  3403242d-663c-4dd6-a83d-0a095f4d709e:
    name: 'Is Featured'
    handle: isFeatured
    instructions: ''
    searchable: false
    translationMethod: none
    translationKeyFormat: null
    type: craft\fields\Lightswitch
    settings:
      default: ''
    contentColumnType: boolean
    fieldGroup: be00446b-966b-45a7-87ca-825ec46f6c22
sections:
  88a67f91-f1b0-472b-8f0d-a13974087779:
    name: 'News Post'
    handle: news
    type: channel
    enableVersioning: true
    propagationMethod: all
    siteSettings:
      f5a5e7be-5c74-4166-981c-41fb37bfee20:
        enabledByDefault: true
        hasUrls: true
        uriFormat: 'news/{slug}'
        template: ''
    entryTypes:
      daca1427-d71f-404d-99cb-e8e979817506:
        name: News
        handle: news
        hasTitleField: true
        titleLabel: Title
        titleFormat: ''
        sortOrder: 1
        fieldLayouts:
          c30bee85-a9f9-4644-a95c-894a393817fd:
            tabs:
              -
                name: Common
                sortOrder: 1
                fields:
                  3403242d-663c-4dd6-a83d-0a095f4d709e:
                    required: false
                    sortOrder: 1
siteGroups:
  f538471f-3c81-42fb-abbb-0b62442ce82b:
    name: 'Tmi Heroku Craft'
sites:
  f5a5e7be-5c74-4166-981c-41fb37bfee20:
    siteGroup: f538471f-3c81-42fb-abbb-0b62442ce82b
    name: 'Craft test site'
    handle: default
    language: en-US
    hasUrls: true
    baseUrl: $DEFAULT_SITE_URL
    sortOrder: 1
    primary: true
system:
  edition: solo
  name: 'Tmi Heroku Craft'
  live: true
  schemaVersion: 3.2.12
  timeZone: America/Los_Angeles
users:
  requireEmailVerification: true
  allowPublicRegistration: false
  defaultGroup: null
  photoVolumeUid: null
  photoSubpath: ''

And my .env:

# The environment Craft is currently running in ('dev', 'staging', 'production', etc.)
ENVIRONMENT="dev"

# The secure key Craft will use for hashing and encrypting data
SECURITY_KEY="REDACTED"

# The database driver that will be used ('mysql' or 'pgsql')
DB_DRIVER="mysql"

# The database server name or IP address (usually this is 'localhost' or '127.0.0.1')
DB_SERVER="localhost"

# The database username to connect with
DB_USER="REDACTED"

# The database password to connect with
DB_PASSWORD="REDACTED"

# The name of the database to select
DB_DATABASE="tmi-heroku-craft"

# The database schema that will be used (PostgreSQL only)
DB_SCHEMA="public"

# The prefix that should be added to generated table names (only necessary if multiple things are sharing the same database)
DB_TABLE_PREFIX=""

# The port to connect to the database with. Will default to 5432 for PostgreSQL and 3306 for MySQL.
DB_PORT=""

DEFAULT_SITE_URL="http://tmi-heroku-craft.test"

Think I found where this is happening but not entirely sure how to correct it!

If I have the _fixtures() method in my functional tests and I do a var_dump() on $basePaths in web/View.php:709 here's what I get:

vendor/craftcms/cms/src/web/View.php:709:
array(1) {
  [0] =>
  string(72) "/MY_PROJECT_PATH/vendor/craftcms/cms/src/templates"
}

But if I comment out the _fixtures() method here's what that $basePaths outputs:

array(1) {
  [0] =>
  string(48) "/MY_PROJECT_PATH/templates"
}

So strange! Not sure why this changes when I call my fixture. Maybe that helps a bit here?

Sorry—dropping some more info here! Looks like this is happening because Craft thinks this is a console request and sets the template mode to cp in web/View.php:234

When _fixtures() is added $request->getIsConsoleRequest() is true. When _fixtures() is removed this same function renders false

@aaronbushnell PR'd a fix for this. It also has some basic explanation about _why_ this was happening. I ran your test suite with all green so it should work on your side as well.

Thanks a bunch for the debugging work and for submitting all the files.

That's fantastic, thanks so much for the quick fix on this @gtettelaar! 🎉

Was this page helpful?
0 / 5 - 0 ratings