droptica/codeception-drupal-content-types

一个Codeception模块,提供Drupal内容类型支持。

1.4.5 2016-06-16 10:16 UTC

README

一个Codeception模块,提供一组封装Drupal内容类型的类。这使得测试与内容类型相关的标准Drupal功能变得更加容易,考虑到它们在您网站上的存在。

它将测试许多事情,例如内容类型管理页面、每个内容类型的“管理字段”页面,并提供一个有用的createNode()方法,可以用来快速创建测试节点,您可以通过特定的值、随机值或随机选择一个值的值范围来提供测试数据。

安装

使用composer安装,如下所示

{
    "repositories": [
        {
            "type": "vcs",
            "url": "https://github.com/ixis/codeception-drupal-content-types.git"
        }
    ],
    "require": {
        "codeception/codeception": "2.*",
        "ixis/codeception-drupal-content-types": "~1.4",
    },
}

将模块添加到套件配置

modules:
    enabled:
        - DrupalContentTypeRegistry

配置

在测试根目录中放置一个contentTypes.yml(除非您想要为每个套件创建一个特定的contentTypes.yml,在这种情况下,请参阅下面)。

以下是一个示例文件

GlobalFields:
    body:
        machineName:    body
        label:          Body
        type:           Long text and summary
        selector:       "#edit-body-und-0-value"
        widget:         Text area with a summary
        required:       true
    title:
        machineName:    title
        label:          Title
        type:           Node module element
        selector:       "#edit-title"
ContentTypes:
    news:
        humanName:    News
        machineName:  news
        fields:
            globals:
                - title
                - body
            field_image:
                machineName:    field_image
                label:          Image
                type:           Image
                selector:       "#edit-field-image"
                widget:         Media file selector
                required:       true
                testData:       "image1.png"
            field_icon:
                machineName:    field_icon
                label:          Icon
                type:           Text
                selector:       "#edit-field-icon"
                widget:         Text field
                skipRoles:
                    - editor
                    - publisher
                testData:
                    - smiley
                    - grumpy
                    - happy
                    - wacky
                preSteps:
                    - ["click", ["#button"]]
                    - ["fillField", ["#the-field", "the-value"]]
                postSteps:
                    - ["waitForJs", ["return jQuery.active == 0;"]]
        submit: "#edit-submit-me-please"

全局字段

在第一部分中,您可以定义将在网站上所有内容类型中使用的字段。这对于标题和正文字段等事物很有用,这样可以节省您在每种内容类型上重新定义确切的同一字段。

全局字段通过机器名键入(这应该是Drupal字段的机器名相同)并且值与它们为内容类型的字段声明的值相同(见下文)。

全局额外信息

与上面的全局字段一样,您可以为网站上的所有内容类型定义额外信息。例如,如果您总是想填充节点的发布状态,无论其类型如何,这很有用。有关更多信息,请参阅下面的“额外信息”部分。

内容类型

每个内容类型应根据其机器名键入(尽管这只是提示,因为machineName负责实际的命名,所以您可以给内容类型任何键)。

  • humanName是在UI中命名内容类型的方式(并且是区分大小写的)。
  • machineName是Drupal中命名内容类型的方式,应该与Drupal中设置的任何内容匹配。
  • fields是内容类型上的所有字段及其属性的列表。
    • globalFields是此类型上“重复使用”的字段的简单列表。如果您的内容类型具有仅从另一个内容类型精确复用字段的字段,请在上面的全局字段中设置它,并在此处仅引用它。一个例外是,如果您设置了标题,但将其标签从“标题”更改为其他内容,在这种情况下,它将不能成为全局字段。
    • properties:字段可以有以下属性...
      • machineName是Drupal看到的字段的机器名。通常这些将以field_开头,但也可能有例外,如标题和正文字段。
      • label是此字段的名称(标签),应与UI中设置的确切内容匹配,包括大小写。
      • type是Drupal UI上“管理字段”页面设置的字段类型。区分大小写。
      • 选择器 是用于在创建或编辑页面中选择该字段元素的 CSS 或 XPath 选择器。请注意,这通常是可选的,如果省略,将根据字段名推导,这通常足够。
      • 小部件 是在 Druapl UI 的“管理字段”页面上为该字段设置的小部件名称。区分大小写。一些字段没有小部件(如标题),因此只需省略即可。有一个字段类型列表,这些类型不需要小部件,因此 ContentTypeRegistry 将知道这一点。
      • 必填 可以设置为“true”,如果字段是必填的。如果不是,则完全省略。
      • 前缀 可以用来指定在填充字段之前应点击的元素的 XPath 选择器。如果设置了此选项,则将点击该元素,然后填充字段。如果没有设置,则在填充字段之前不会点击任何内容。这对于位于垂直标签后面的元素很有用,这些元素在用户未首先选择垂直标签的情况下不会对用户可见。
      • 跳过的角色 是一个角色名称数组,将无法看到此字段,也不应尝试填充它。
      • 测试数据 应包含用于测试此字段的虚拟数据。每个字段都可以指示其自动用测试数据填充,这将使用的数据。请注意,除非字段是必填的,并且 Drupal 为该字段没有提供默认值,否则可以省略 yaml 中的 testData。如果提供了值数组,则 Field 类可以随机选择一个。也可以在这里使用特殊值。请参阅下面的“特殊值”。
      • 前步骤 是在填充字段之前运行的可选步骤。这是对 前缀 选项的扩展,但可以运行任何方法,而不仅仅是点击。格式是一个包含两个元素的数组。第一个元素是方法名称,第二个元素是要传递给方法的参数数组。例如,["checkOption", ["#checkbox-name"]] 将在填充字段之前调用 $I->checkOption("#checkbox-name")
      • 后步骤 是在填充字段后运行的可选步骤。例如,["waitForJs", ["return jQuery.active == 0;"]] 将在字段填充后等待 AJAX 调用完成,然后再继续。
  • 额外内容 是所有额外内容(在节点编辑表单上与之交互的元素)的列表,它们本身不是字段。下面将提供更多信息。
    • 全局额外内容 是在此类型上的“重复使用”额外内容的列表。这与 globalFields 的工作方式相同,但是用于节点表单上的不是字段的东西。
  • 提交 是用于在节点添加或编辑表单上查找提交按钮的 CSS 或 XPath。Drupal 的默认值是 "#edit-submit",如果您在网站上使用默认值,则可以省略。

特殊值

您可以使用特殊值,该值将在每次创建字段时用于测试。如果您想插入随机值,这很有用。所有特殊值都以标识符 special:: 开头,然后跟特殊值的类型。类型如下列出

  • 随机文本 使用八个随机字母数字字符。

示例

testData: "special::randomText"

特定小部件类型

地址小部件

将此小部件的选择器设置为小部件内每个单独地址字段的第一个部分。例如,如果机器名称是 field_address,则您会设置选择器如下

selector:   "#edit-field-address-und-0"

您需要定义地址小部件中包含的各个元素,因为这些元素可以按小部件分别定义。

您可以使用elements键来完成这项操作。数组键是每个字段的标签,值是用于选择器的末尾部分,该部分与上面描述的选择器连接。

elements:
    Company:        "-organisation"
    Address 1:      "-thoroughfare"
    Address 2:      "-locality"
    "Town/City":    "-locality"

如果您需要为该字段设置testData,则需要将以下方式包围每个测试元素组:

testData:
    address1:
        Company:        Test location
        Address 1:      Test location thoroughfare
        Address 2:      Test location locality
        "Town/City":    Test location city
        County:         Test location county
        Postcode:       Test location postal code
    # Then, if necessary:
    address2:
        Company:        Test location 2
        Address 1:      Test location thoroughfare 2
        Address 2:      Test location locality 2
        "Town/City":    Test location city 2
        County:         Test location county 2
        Postcode:       Test location postal code 2

复选框小部件

请记住,您只需要设置testData,如果每个或任何复选框的值需要更改。

如果您需要为复选框小部件设置testData,请确保将每个盒子组放入自己的包装器中,如下所示:

testData:
    values1:
        Grapefruit: true
        Melon:      false
        Avocado:    true
    values2:
        "Big Hairy Kiwi Fruit/Kiwi Fruits": true

所见即所得小部件

使用此功能用于所见即所得字段。选择器应该是此字段的文本区域元素的ID,但不要在末尾包含"-value"部分。例如,对于正文字段,您可能会使用

selector: "#edit-body-und-0"

当前小部件将切换到纯文本格式以输入数据。

套件特定的contentTypes.yml

如果您愿意,可以在每个套件文件夹中放置单独的contentTypes.yml,这些文件可以覆盖主contentTypes.yml(或者在测试根文件夹中不创建主的一个)。

如果您这样做,您需要在您的套件的 _bootstrap.php中添加以下内容

\Codeception\Module\Drupal\ContentTypeRegistry\SuiteSettings::$suiteName = 'mysuite';

套件名称应该与套件所在目录的名称匹配。这是因为Codeception没有其他方法知道在尝试查找contentTypes.yml文件时应该查找哪个目录。它知道根测试目录的位置,并且有一个它应该运行的套件列表,但不能确定当前套件运行的目录。如果将来在Codeception中开发了一种实现此目的的方法,则可以删除此额外步骤。

额外工具

有时,您可能想要模拟用户在节点编辑表单上点击不是字段的项。这就是额外工具的用武之地。您可以像设置节点粘性状态或发布状态这样的操作。以下是一个示例

ContentTypes:
    news:
        humanName:    News
        machineName:  news
        fields:
            globals:
                - title
                - body
            field_image:
                machineName:    field_image
                label:          Image
                type:           Image
                selector:       "#edit-field-image"
                widget:         Media file selector
                required:       true
                testData:       "image1.png"
        extras:
            published:
                machineName:    published
                label:          Published
                type:           List (text)
                selector:       "#edit-published"
                widget:         Select list
                testData:       Published
        submit: "#edit-submit-me-please"

如你所见,这些与字段并排。您通常需要手动设置选择器,因为这些应用于字段的命名约定不适用于此处。您仍然可以使用widget属性来告诉此模块正在使用哪种类型的表单小部件。

节点创建/删除

在createNode/deleteNode期间,通过在元素中查找标准Drupal消息来检查成功状态,例如.messages

某些主题可能具有不同的选择器,或者根本不显示这些消息。如果是这样,您可以在您的套件辅助器中实现seeCreateNodeWasSuccessful()和/或seeDeleteNodeWasSuccessful()

例如:

class AcceptanceHelper extends \Codeception\Module
{
    /**
     * Check a node creation was successful.
     *
     * This overrides the default since the css selectors are different in
     * this site's theme.
     *
     * @see DrupalContentTypeRegistry::seeCreateNodeWasSuccessful()
     *
     * @param WebInterface $I
     *   A reference to the Actor being used.
     * @param string $msg
     *   The success message that should be displayed by Drupal.
     * @param int $nid
     *   The created nid.
     */
    public function seeCreateNodeWasSuccessful($I, $msg, $nid)
    {
        $I->see($msg, ".messages");
        $I->dontSee(" ", ".messages.error");
    }

    /**
     * Check a node deletion was successful.
     *
     * This overrides the default since this site redirects to the
     * homepage on node deletion and does not show a message. We
     * therefore do a check by editing the node and make sure it's
     * not found.
     *
     * @see DrupalContentTypeRegistry::seeDeleteNodeWasSuccessful()
     *
     * @param AuthenticatedSteps $I
     *   A reference to the Actor being used.
     * @param int $nid
     *   The deleted nid.
     */
    public function seeDeleteNodeWasSuccessful($I, $nid)
    {
        $I->amOnPage(NodePage::route($nid, true));
        $I->see("we can't find this page", "h1");
    }
}