'Zero', 1 => 'One', 2 => 'Two', 3 => 'Three'] ); $f->setValue([0,1]); $f->setDefaultItems([2]); $p = new CSSContentParser($f->Field()); $item0 = $p->getBySelector('#Test_0'); $item1 = $p->getBySelector('#Test_1'); $item2 = $p->getBySelector('#Test_2'); $item3 = $p->getBySelector('#Test_3'); $this->assertEquals( (string)$item0[0]['checked'], 'checked', 'Selected through value' ); $this->assertEquals( (string)$item1[0]['checked'], 'checked', 'Selected through value' ); $this->assertEquals( (string)$item2[0]['checked'], 'checked', 'Selected through default items' ); $this->assertEquals( (string)$item3[0]['checked'], '', 'Not selected by either value or default items' ); } /** * Test different data sources */ public function testSources() { // Array $items = ['a' => 'Apple', 'b' => 'Banana', 'c' => 'Cranberry']; $field = new CheckboxSetField('Field', null, $items); $this->assertEquals($items, $field->getSource()); // SS_List $list = new ArrayList( [ new ArrayData( [ 'ID' => 'a', 'Title' => 'Apple' ] ), new ArrayData( [ 'ID' => 'b', 'Title' => 'Banana' ] ), new ArrayData( [ 'ID' => 'c', 'Title' => 'Cranberry' ] ) ] ); $field2 = new CheckboxSetField('Field', null, $list); $this->assertEquals($items, $field2->getSource()); $field3 = new CheckboxSetField('Field', null, $list->map()); $this->assertEquals($items, $field3->getSource()); } public function testSaveWithNothingSelected() { $article = $this->objFromFixture(Article::class, 'articlewithouttags'); /* Create a CheckboxSetField with nothing selected */ $field = new CheckboxSetField("Tags", "Test field", DataObject::get(Tag::class)->map()); /* Saving should work */ $field->saveInto($article); $this->assertNull( DB::prepared_query( "SELECT * FROM \"CheckboxSetFieldTest_Article_Tags\" WHERE \"CheckboxSetFieldTest_Article_Tags\".\"CheckboxSetFieldTest_ArticleID\" = ?", [$article->ID] )->value(), 'Nothing should go into manymany join table for a saved field without any ticked boxes' ); } public function testSaveWithArrayValueSet() { $article = $this->objFromFixture(Article::class, 'articlewithouttags'); $articleWithTags = $this->objFromFixture(Article::class, 'articlewithtags'); $tag1 = $this->objFromFixture(Tag::class, 'tag1'); $tag2 = $this->objFromFixture(Tag::class, 'tag2'); /* Create a CheckboxSetField with 2 items selected. Note that the array is a list of values */ $field = new CheckboxSetField("Tags", "Test field", DataObject::get(Tag::class)->map()); $field->setValue( [ $tag1->ID, $tag2->ID ] ); /* Saving should work */ $field->saveInto($article); $this->assertEquals( [$tag1->ID,$tag2->ID], DB::prepared_query( "SELECT \"CheckboxSetFieldTest_TagID\" FROM \"CheckboxSetFieldTest_Article_Tags\" WHERE \"CheckboxSetFieldTest_Article_Tags\".\"CheckboxSetFieldTest_ArticleID\" = ?", [$article->ID] )->column(), 'Data shold be saved into CheckboxSetField manymany relation table on the "right end"' ); $this->assertEquals( [$articleWithTags->ID,$article->ID], DB::query( "SELECT \"CheckboxSetFieldTest_ArticleID\" FROM \"CheckboxSetFieldTest_Article_Tags\" WHERE \"CheckboxSetFieldTest_Article_Tags\".\"CheckboxSetFieldTest_TagID\" = $tag1->ID " )->column(), 'Data shold be saved into CheckboxSetField manymany relation table on the "left end"' ); } public function testLoadDataFromObject() { $articleWithTags = $this->objFromFixture(Article::class, 'articlewithtags'); $tag1 = $this->objFromFixture(Tag::class, 'tag1'); $tag2 = $this->objFromFixture(Tag::class, 'tag2'); $field = new CheckboxSetField("Tags", "Test field", DataObject::get(Tag::class)->map()); /** @skipUpgrade */ $form = new Form( Controller::curr(), 'Form', new FieldList($field), new FieldList() ); $form->loadDataFrom($articleWithTags); $value = $field->Value(); sort($value); $this->assertEquals( [ $tag1->ID, $tag2->ID ], $value, 'CheckboxSetField loads data from a manymany relationship in an object through Form->loadDataFrom()' ); } public function testSavingIntoTextField() { $field = new CheckboxSetField( 'Content', 'Content', [ 'Test' => 'Test', 'Another' => 'Another', 'Something' => 'Something' ] ); $article = new CheckboxSetFieldTest\Article(); $field->setValue(['Test' => 'Test', 'Another' => 'Another']); $field->saveInto($article); $article->write(); $dbValue = DB::query( sprintf( 'SELECT "Content" FROM "CheckboxSetFieldTest_Article" WHERE "ID" = %s', $article->ID ) )->value(); // JSON encoded values $this->assertEquals('["Test","Another"]', $dbValue); } public function testValidationWithArray() { // Test with array input $field = CheckboxSetField::create( 'Test', 'Testing', [ "One" => "One", "Two" => "Two", "Three" => "Three" ] ); $validator = new RequiredFields(); $field->setValue(["One", "Two"]); $this->assertTrue( $field->validate($validator), 'Field validates values within source array' ); // Non valid value should fail $field->setValue(["Four" => "Four"]); $this->assertFalse( $field->validate($validator), 'Field does not validate values outside of source array' ); // Non valid value, even if included with valid options, should fail $field->setValue(["One", "Two", "Four"]); $this->assertFalse( $field->validate($validator), 'Field does not validate when presented with mixed valid and invalid values' ); } public function testValidationWithDataList() { //test with datalist input $checkboxTestArticle = $this->objFromFixture(Article::class, 'articlewithtags'); $tag1 = $this->objFromFixture(Tag::class, 'tag1'); $tag2 = $this->objFromFixture(Tag::class, 'tag2'); $tag3 = $this->objFromFixture(Tag::class, 'tag3'); $field = CheckboxSetField::create('Test', 'Testing', $checkboxTestArticle->Tags()); $validator = new RequiredFields(); $field->setValue([ $tag1->ID, $tag2->ID ]); $isValid = $field->validate($validator); $this->assertTrue( $isValid, 'Validates values in source map' ); // Invalid value should fail $validator = new RequiredFields(); $fakeID = CheckboxSetFieldTest\Tag::get()->max('ID') + 1; $field->setValue([$fakeID]); $this->assertFalse( $field->validate($validator), 'Field does not valid values outside of source map' ); $errors = $validator->getErrors(); $error = reset($errors); $this->assertEquals( _t( 'SilverStripe\\Forms\\MultiSelectField.SOURCE_VALIDATION', "Please select values within the list provided. Invalid option(s) {value} given", ['value' => $fakeID] ), $error['message'] ); // Multiple invalid values should fail $validator = new RequiredFields(); $fakeID = Tag::get()->max('ID') + 1; $field->setValue([$fakeID, $tag3->ID]); $this->assertFalse( $field->validate($validator), 'Field does not valid values outside of source map' ); $errors = $validator->getErrors(); $error = reset($errors); $this->assertEquals( _t( 'SilverStripe\\Forms\\MultiSelectField.SOURCE_VALIDATION', "Please select values within the list provided. Invalid option(s) {value} given", ['value' => implode(',', [$fakeID, $tag3->ID])] ), $error['message'] ); // Invalid value with non-array value $validator = new RequiredFields(); $field->setValue($fakeID); $this->assertFalse( $field->validate($validator), 'Field does not valid values outside of source map' ); $errors = $validator->getErrors(); $error = reset($errors); $this->assertEquals( _t( 'SilverStripe\\Forms\\MultiSelectField.SOURCE_VALIDATION', "Please select values within the list provided. Invalid option(s) {value} given", ['value' => $fakeID] ), $error['message'] ); //non valid value included with valid options should succeed $validator = new RequiredFields(); $field->setValue( [ $tag1->ID, $tag2->ID, $tag3->ID ] ); $this->assertFalse( $field->validate($validator), 'Field does not validate when presented with mixed valid and invalid values' ); } public function testSafelyCast() { $member = new Member(); $member->FirstName = ''; $member->Surname = ''; $member->write(); $field1 = new CheckboxSetField( 'Options', 'Options', [ 'one' => 'One', 'two' => 'Two & Three', 'three' => DBField::create_field('HTMLText', 'Four & Five & Six'), 'four' => $member->FirstName, ] ); $fieldHTML = (string)$field1->Field(); $this->assertStringContainsString('One', $fieldHTML); $this->assertStringContainsString('Two & Three', $fieldHTML); $this->assertStringNotContainsString('Two & Three', $fieldHTML); $this->assertStringContainsString('Four & Five & Six', $fieldHTML); $this->assertStringNotContainsString('Four & Five & Six', $fieldHTML); $this->assertStringContainsString('<firstname>', $fieldHTML); $this->assertStringNotContainsString('', $fieldHTML); } /** * #2939 CheckboxSetField creates invalid HTML when required */ public function testNoAriaRequired() { $field = new CheckboxSetField('RequiredField', 'myRequiredField'); $form = new Form( Controller::curr(), "form", new FieldList($field), new FieldList(), new RequiredFields(["RequiredField"]) ); $this->assertTrue($field->Required()); $attributes = $field->getAttributes(); $this->assertFalse(array_key_exists("aria-required", $attributes)); $this->assertFalse(array_key_exists("name", $attributes)); $this->assertFalse(array_key_exists("required", $attributes)); } }