Googleを検索しましたが、答えが見つかりません。 Stack Exchangeは私の最後の手段です。
私のフォームには、2つの選択フィールドがあります。
_$form['system']['foo'] = array(
...
'#type' => 'select',
'#options' => array('A', 'B', 'C'),
...
'#ajax' => array(
'event' => 'change',
...
'method' => 'replace',
),
);
$form['system']['bar'] = array(
...
'#type' => 'select',
'#options' => array(),
'#prefix' => ...
'#suffix' => ...
);
_
ユーザーがfoo
フィールドのオプションのいずれかを選択した場合、bar
フィールドはajaxを介してオプションを動的にロードします。例:「A」がfoo
で選択されている場合、bar
フィールドは「aaa」、「bbb」、「ccc」などのオプションを生成し、ユーザーが選択できます。
このフォームは機能し、「Simpletest」を使用してユニットテストを提供する必要があります。
私のテストケースでは:
_$edit = array(
'system[foo]' => 1, // value for 'A'
'system[bar]' => 2, // value for 'bbb'
);
$this->drupalPost('mymodule/mypath', $edit, t('Submit'));
_
_system[bar]
_を2に設定できないことを示すエラーが発生します(まだ2の値がないため?)
_system[foo]
_を設定する前に、_system[bar]
_でajax呼び出しをエミュレートする必要があります。
私はdrupalPostAjax
を試しました:
_$edit = array(
'system[foo]' => 1, // value for A
);
$this->drupalPostAjax('mymodule/mypath', $edit, 'system[foo]');
_
ajaxで成功した結果が得られます。コードの次の行で、前のコードスニペットを使用してdrupalPost()
をもう一度呼び出してみましたが、_system[bar]
_を2に設定できないという同じエラーが表示されます。
どうすれば問題を解決できますか?それは私を大いに助けることができるので、サンプルコードを提供してください。
編集:
Ajaxは実際のページで機能します(つまり、値は_system['bar']
_に動的にロードされます)。したがって、フォーム内のコードが機能していると想定できます。
ただし、ajaxがSimpletestから生成されたページ(sites/default/files/simpletest/verboseにあるページ)では機能しないことに気づきました。 GoogleのコンソールChromeはエラーを表示しません。Ajaxはステータス200を返しますが、応答はありません。
インストール時にデフォルトのテーマを使用しています。
編集:フォームとシンプルなコード
フォーム:znerolが投稿したフォームをコピーしました。
最も単純なコード:
_class MyModuleTestCase extends DrupalWebTestCase {
protected $admin_user;
public static function getInfo() {
return array(
'name' => 'Test Case name',
'description' => 'Test Case Description',
'group' => 'My Module',
);
}
public function setUp() {
// Enable module
parent::setUp(array('mymodule'));
// Get permissions
$permissions = mymodule_get_permissions();
// Permissions obtained correctly.
// Create and login admin user
$this->admin_user = $this->drupalCreateUser($permissions);
$this->drupalLogin($this->admin_user);
}
// Test section
public function testSystem() {
$this->drupalGet('mymodule/mypath');
$edit = array(
'system[foo]' => 1, // Selects 'A'. Tested!
);
$this->drupalPostAjax(NULL, $edit, 'system[foo]');
// Bar after ajax is loaded
$edit = array(
'system[bar]' => 1, // Selects 'aaa'
);
$this->drupalPost(NULL, $edit, t('Submit')); // Error here.
$this->assertText(t('Submitted!'));
}
}
_
ただし、simpletestを実行すると、simpletestは_system['bar']
_を_1
_(aaa)に設定できないと不平を言います。
Simpletestがajaxを呼び出す前に次の警告を表示することに気づきました。
未定義のオフセット:0通知drupal_web_test_case.php 2147 DrupalWebTestCase> drupalPostAJAX()
未定義のインデックス:drupal_web_test_case.php 2148 DrupalWebTestCase-> drupalPostAJAX()に注意してください
未定義のインデックス:#ajax Notice ajax.inc 379 ajax_form_callback()
_system['bar']
_はajaxを介して動的にロードされるため、最初は空の配列array()
があります。上記の警告から、_system['bar']
_に一時オプションarray('1', '2')
を追加してみました。同じエラーと警告が発生します。
$path
パラメータをNULL
に送信すると、同じフォームに送信されます。それ以外の場合、drupalPost/drupalPostAJAXはまずページを再度取得し、現在のフォームを再構築する代わりに新しいフォームを生成します。
次のテストはあなたが望むことをするはずです:
// First retrieve the page once
$this->drupalGet('mymodule/mypath');
// Set $path to NULL on subsequent requests to the same form
$edit = array('system[foo]' => 1);
$this->drupalPostAJAX(NULL, $edit, 'system[foo]');
$edit = array('system[bar]' => 2);
$this->drupalPost(NULL, $edit, t('Submit'));
テストケースは、次のフォームで実行すると成功します。
function mymodule_myform($form, &$form_state) {
$foo_options = array('A', 'B', 'C');
$foo_default = isset($form_state['values']['system']['foo']) ? $form_state['values']['system']['foo'] : NULL;
$form['system']['#tree'] = TRUE;
$form['system']['foo'] = array(
'#type' => 'select',
'#options' => $foo_options,
'#default_value' => $foo_default,
'#ajax' => array(
'callback' => 'mymodule_myform_ajax_callback',
'wrapper' => 'bar-div',
'method' => 'replace',
),
);
$bar_choices = array(
0 => array('aaa', 'bbb', 'ccc'),
1 => array('ddd', 'eee', 'fff'),
2 => array('ggg', 'hhh', 'iii'),
);
$form['system']['bar'] = array(
'#prefix' => '<div id="bar-div">',
'#suffix' => '</div>',
'#type' => 'select',
'#options' => isset($bar_choices[$foo_default]) ? $bar_choices[$foo_default] : array(),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
);
return $form;
}
function mymodule_myform_ajax_callback($form, $form_state) {
return $form['system']['bar'];
}
あなたの次のコードで私が気付いた1つのこと:
$form['system']['foo'] = array(
...
'#type' => 'select',
'#options' => array('A', 'B', 'C'),
...
'#ajax' => array(
'event' => 'change',
...
'method' => 'replace',
),
);
$form['system']['bar'] = array(
...
'#type' => 'select',
'#options' => array(),
'#prefix' => ...
'#suffix' => ...
);
system[bar]
フィールドが空の配列で初期化されました:array()。
そして、オプションを含まないそのフィールドの値を設定しようとしているよりも。私の推測では、system[bar]
フィールドのオプションも初期化できますか。 bar
フィールドがajaxを介してオプションを動的にロードすることを述べたのは知っています。しかし、そのフィールドの値は、適切な結果セットで初期化されない限り設定できないと思います。