Merge branch 'master' of https://github.com/bagisto/bagisto into development

This commit is contained in:
rahul shukla 2020-01-03 18:05:24 +05:30
commit 7f3e3001b5
17 changed files with 449 additions and 54 deletions

File diff suppressed because one or more lines are too long

View File

@ -545,6 +545,7 @@ return [
'file' => 'File',
'checkbox' => 'Checkbox',
'use_in_flat' => "Create in Product Flat Table",
'default_null_option' => 'Create default empty option',
],
'families' => [
'title' => 'Families',

View File

@ -252,6 +252,15 @@
</select>
</div>
<div class="control-group">
<span class="checkbox">
<input type="checkbox" class="control" id="default-null-option" name="default-null-option" v-model="isNullOptionChecked" >
<label class="checkbox-view" for="default-null-option"></label>
{{ __('admin::app.catalog.attributes.default_null_option') }}
</span>
</div>
<div class="table">
<table>
<thead>
@ -292,7 +301,7 @@
@foreach (app('Webkul\Core\Repositories\LocaleRepository')->all() as $locale)
<td>
<div class="control-group" :class="[errors.has(localeInputName(row, '{{ $locale->code }}')) ? 'has-error' : '']">
<input type="text" v-validate="'{{ app()->getLocale() }}' == '{{ $locale->code }}' ? 'required': ''" v-model="row['{{ $locale->code }}']" :name="localeInputName(row, '{{ $locale->code }}')" class="control" data-vv-as="&quot;{{ $locale->name . ' (' . $locale->code . ')' }}&quot;"/>
<input type="text" v-validate="getOptionValidation(row, '{{ $locale->code }}')" v-model="row['{{ $locale->code }}']" :name="localeInputName(row, '{{ $locale->code }}')" class="control" data-vv-as="&quot;{{ $locale->name . ' (' . $locale->code . ')' }}&quot;"/>
<span class="control-error" v-if="errors.has(localeInputName(row, '{{ $locale->code }}'))">@{{ errors.first(localeInputName(row, '{!! $locale->code !!}')) }}</span>
</div>
</td>
@ -313,7 +322,7 @@
</table>
</div>
<button type="button" class="btn btn-lg btn-primary mt-20" id="add-option-btn" @click="addOptionRow()">
<button type="button" class="btn btn-lg btn-primary mt-20" id="add-option-btn" @click="addOptionRow(false)">
{{ __('admin::app.catalog.attributes.add-option-btn-title') }}
</button>
</div>
@ -339,10 +348,12 @@
data: function() {
return {
optionRowCount: 0,
optionRowCount: 1,
optionRows: [],
show_swatch: false,
swatch_type: ''
swatch_type: '',
isNullOptionChecked: false,
idNullOption: null
}
},
@ -361,19 +372,32 @@
},
methods: {
addOptionRow: function () {
var rowCount = this.optionRowCount++;
var row = {'id': 'option_' + rowCount};
addOptionRow: function (isNullOptionRow) {
const rowCount = this.optionRowCount++;
const id = 'option_' + rowCount;
let row = {'id': id};
@foreach (app('Webkul\Core\Repositories\LocaleRepository')->all() as $locale)
row['{{ $locale->code }}'] = '';
@endforeach
row['notRequired'] = '';
if (isNullOptionRow) {
this.idNullOption = id;
row['notRequired'] = true;
}
this.optionRows.push(row);
},
removeRow: function (row) {
var index = this.optionRows.indexOf(row)
if (row.id === this.idNullOption) {
this.idNullOption = null;
this.isNullOptionChecked = false;
}
const index = this.optionRows.indexOf(row);
Vue.delete(this.optionRows, index);
},
@ -387,6 +411,28 @@
sortOrderName: function (row) {
return 'options[' + row.id + '][sort_order]';
},
getOptionValidation: (row, localeCode) => {
if (row.notRequired === true) {
return '';
}
return ('{{ app()->getLocale() }}' === localeCode) ? 'required' : '';
}
},
watch: {
isNullOptionChecked: function (val) {
if (val) {
if (! this.idNullOption) {
this.addOptionRow(true);
}
} else if(this.idNullOption !== null && typeof this.idNullOption !== 'undefined') {
const row = this.optionRows.find(optionRow => optionRow.id === this.idNullOption);
this.removeRow(row);
}
}
}
})

View File

@ -316,6 +316,15 @@
</select>
</div>
<div class="control-group">
<span class="checkbox">
<input type="checkbox" class="control" id="default-null-option" name="default-null-option" v-model="isNullOptionChecked">
<label class="checkbox-view" for="default-null-option"></label>
{{ __('admin::app.catalog.attributes.default_null_option') }}
</span>
</div>
<div class="table">
<table>
<thead>
@ -337,6 +346,7 @@
</thead>
<tbody>
<tr v-for="(row, index) in optionRows">
<td v-if="show_swatch && swatch_type == 'color'">
<swatch-picker :input-name="'options[' + row.id + '][swatch_value]'" :color="row.swatch_value" colors="text-advanced" show-fallback />
@ -357,7 +367,7 @@
@foreach (app('Webkul\Core\Repositories\LocaleRepository')->all() as $locale)
<td>
<div class="control-group" :class="[errors.has(localeInputName(row, '{{ $locale->code }}')) ? 'has-error' : '']">
<input type="text" v-validate="'{{ app()->getLocale() }}' == '{{ $locale->code }}' ? 'required': ''" v-model="row['{{ $locale->code }}']" :name="localeInputName(row, '{{ $locale->code }}')" class="control" data-vv-as="&quot;{{ $locale->name . ' (' . $locale->code . ')' }}&quot;"/>
<input type="text" v-validate="getOptionValidation(row, '{{ $locale->code }}')" v-model="row['{{ $locale->code }}']" :name="localeInputName(row, '{{ $locale->code }}')" class="control" data-vv-as="&quot;{{ $locale->name . ' (' . $locale->code . ')' }}&quot;"/>
<span class="control-error" v-if="errors.has(localeInputName(row, '{{ $locale->code }}'))">@{{ errors.first(localeInputName(row, '{!! $locale->code !!}')) }}</span>
</div>
</td>
@ -396,22 +406,31 @@
optionRowCount: 0,
optionRows: [],
show_swatch: "{{ $attribute->type == 'select' ? true : false }}",
swatch_type: "{{ $attribute->swatch_type }}"
swatch_type: "{{ $attribute->swatch_type }}",
isNullOptionChecked: false,
idNullOption: null
}
},
created: function () {
@foreach ($attribute->options as $option)
this.optionRowCount++;
var row = {
'id': '{{ $option->id }}',
'admin_name': '{{ $option->admin_name }}',
'sort_order': '{{ $option->sort_order }}',
'sort_order': '{{ $option->sort_order }}',
'swatch_value': '{{ $option->swatch_value }}',
'swatch_value_url': '{{ $option->swatch_value_url }}'
'swatch_value_url': '{{ $option->swatch_value_url }}',
'notRequired': ''
};
@if (empty($option->label))
this.isNullOptionChecked = true;
this.idNullOption = '{{ $option->id }}';
row['notRequired'] = true;
@endif
@foreach (app('Webkul\Core\Repositories\LocaleRepository')->all() as $locale)
row['{{ $locale->code }}'] = "{{ $option->translate($locale->code)['label'] }}";
@endforeach
@ -431,19 +450,32 @@
},
methods: {
addOptionRow: function () {
var rowCount = this.optionRowCount++;
var row = {'id': 'option_' + rowCount};
addOptionRow: function (isNullOptionRow) {
const rowCount = this.optionRowCount++;
const id = 'option_' + rowCount;
let row = {'id': id};
@foreach (app('Webkul\Core\Repositories\LocaleRepository')->all() as $locale)
row['{{ $locale->code }}'] = '';
@endforeach
row['notRequired'] = '';
if (isNullOptionRow) {
this.idNullOption = id;
row['notRequired'] = true;
}
this.optionRows.push(row);
},
removeRow: function (row) {
var index = this.optionRows.indexOf(row)
if (row.id === this.idNullOption) {
this.idNullOption = null;
this.isNullOptionChecked = false;
}
const index = this.optionRows.indexOf(row)
Vue.delete(this.optionRows, index);
},
@ -457,6 +489,27 @@
sortOrderName: function (row) {
return 'options[' + row.id + '][sort_order]';
},
getOptionValidation: (row, localeCode) => {
if (row.notRequired === true) {
return '';
}
return ('{{ app()->getLocale() }}' === localeCode) ? 'required' : '';
}
},
watch: {
isNullOptionChecked: function (val) {
if (val) {
if (! this.idNullOption) {
this.addOptionRow(true);
}
} else if(this.idNullOption !== null && typeof this.idNullOption !== 'undefined') {
const row = this.optionRows.find(optionRow => optionRow.id === this.idNullOption);
this.removeRow(row);
}
}
}
});

View File

@ -0,0 +1,84 @@
<?php
/** @var \Illuminate\Database\Eloquent\Factory $factory */
use Faker\Generator as Faker;
use Webkul\Attribute\Models\Attribute;
use Webkul\Core\Models\Locale;
$factory->define(Attribute::class, function (Faker $faker, array $attributes) {
$types = [
'text',
'textarea',
'price',
'boolean',
'select',
'multiselect',
'datetime',
'date',
'image',
'file',
'checkbox',
];
$locales = Locale::pluck('code')->all();
// array $attributes does not contain any locale code
if (count(array_diff_key(array_flip($locales), $attributes) ) === count($locales)) {
$localeCode = $locales[0];
$attributes[$localeCode] = [
'name' => $faker->word,
];
}
return [
'admin_name' => $faker->word,
'code' => $faker->word,
'type' => array_rand($types),
'validation' => '',
'position' => $faker->randomDigit,
'is_required' => false,
'is_unique' => false,
'value_per_locale' => false,
'value_per_channel' => false,
'is_filterable' => false,
'is_configurable' => false,
'is_user_defined' => true,
'is_visible_on_front' => true,
'swatch_type' => null,
'use_in_flat' => true,
];
});
$factory->state(Attribute::class, 'validation_numeric', [
'validation' => 'numeric',
]);
$factory->state(Attribute::class, 'validation_email', [
'validation' => 'email',
]);
$factory->state(Attribute::class, 'validation_decimal', [
'validation' => 'decimal',
]);
$factory->state(Attribute::class, 'validation_url', [
'validation' => 'url',
]);
$factory->state(Attribute::class, 'required', [
'is_required' => true,
]);
$factory->state(Attribute::class, 'unique', [
'is_unique' => true,
]);
$factory->state(Attribute::class, 'filterable', [
'is_filterable' => true,
]);
$factory->state(Attribute::class, 'configurable', [
'is_configurable' => true,
]);

View File

@ -0,0 +1,83 @@
<?php
/** @var \Illuminate\Database\Eloquent\Factory $factory */
use Faker\Generator as Faker;
use Webkul\Attribute\Models\Attribute;
use Webkul\Attribute\Models\AttributeOption;
use Webkul\Core\Models\Locale;
$factory->define(AttributeOption::class, function (Faker $faker, array $attributes) {
$locales = Locale::pluck('code')->all();
// array $attributes does not contain any locale code
if (count(array_diff_key(array_flip($locales), $attributes) ) === count($locales)) {
$localeCode = $locales[0];
$attributes[$localeCode] = [
'label' => $faker->word,
];
}
return [
'admin_name' => $faker->word,
'sort_order' => $faker->randomDigit,
'attribute_id' => function () {
return factory(Attribute::class)->create()->id;
},
'swatch_value' => null,
];
});
$factory->defineAs(AttributeOption::class, 'swatch_color', function (Faker $faker, array $attributes) {
return [
'admin_name' => $faker->word,
'sort_order' => $faker->randomDigit,
'attribute_id' => function () {
return factory(Attribute::class)
->create(['swatch_type' => 'color'])
->id;
},
'swatch_value' => $faker->hexColor,
];
});
$factory->defineAs(AttributeOption::class, 'swatch_image', function (Faker $faker, array $attributes) {
return [
'admin_name' => $faker->word,
'sort_order' => $faker->randomDigit,
'attribute_id' => function () {
return factory(Attribute::class)
->create(['swatch_type' => 'image'])
->id;
},
'swatch_value' => '/tests/_data/ProductImageExampleForUpload.jpg',
];
});
$factory->defineAs(AttributeOption::class, 'swatch_dropdown', function (Faker $faker, array $attributes) {
return [
'admin_name' => $faker->word,
'sort_order' => $faker->randomDigit,
'attribute_id' => function () {
return factory(Attribute::class)
->create(['swatch_type' => 'dropdown'])
->id;
},
'swatch_value' => null,
];
});
$factory->defineAs(AttributeOption::class, 'swatch_text', function (Faker $faker, array $attributes) {
return [
'admin_name' => $faker->word,
'sort_order' => $faker->randomDigit,
'attribute_id' => function () {
return factory(Attribute::class)
->create(['swatch_type' => 'text'])
->id;
},
'swatch_value' => null,
];
});

View File

@ -2,6 +2,7 @@
namespace Webkul\Attribute\Providers;
use Illuminate\Database\Eloquent\Factory as EloquentFactory;
use Illuminate\Support\ServiceProvider;
class AttributeServiceProvider extends ServiceProvider
@ -14,6 +15,8 @@ class AttributeServiceProvider extends ServiceProvider
public function boot()
{
$this->loadMigrationsFrom(__DIR__ . '/../Database/Migrations');
$this->app->make(EloquentFactory::class)->load(__DIR__ . '/../Database/Factories');
}
/**

View File

@ -13,7 +13,7 @@ class View extends AbstractProduct
/**
* Returns the visible custom attributes
*
* @param Product $product
* @param Webkul\Product\Models\Product $product
* @return integer
*/
public function getAdditionalData($product)
@ -36,15 +36,23 @@ class View extends AbstractProduct
} else if($value) {
if ($attribute->type == 'select') {
$attributeOption = $attributeOptionReposotory->find($value);
if ($attributeOption)
$value = $attributeOption->label ?? $attributeOption->admin_name;
if ($attributeOption) {
$value = $attributeOption->label ?? null;
if (! $value) {
continue;
}
}
} else if ($attribute->type == 'multiselect' || $attribute->type == 'checkbox') {
$lables = [];
$attributeOptions = $attributeOptionReposotory->findWhereIn('id', explode(",", $value));
foreach ($attributeOptions as $attributeOption) {
$lables[] = $attributeOption->label ?? $attributeOption->admin_name;
if ($label = $attributeOption->label) {
$lables[] = $label;
}
}
$value = implode(", ", $lables);

View File

@ -112,7 +112,7 @@ class ProductRepository extends Repository
{
$params = request()->input();
$results = app('Webkul\Product\Repositories\ProductFlatRepository')->scopeQuery(function($query) use($params, $categoryId) {
$results = app(ProductFlatRepository::class)->scopeQuery(function($query) use($params, $categoryId) {
$channel = request()->get('channel') ?: (core()->getCurrentChannelCode() ?: core()->getDefaultChannelCode());
$locale = request()->get('locale') ?: app()->getLocale();
@ -212,7 +212,7 @@ class ProductRepository extends Repository
*/
public function findBySlugOrFail($slug, $columns = null)
{
$product = app('Webkul\Product\Repositories\ProductFlatRepository')->findOneWhere([
$product = app(ProductFlatRepository::class)->findOneWhere([
'url_key' => $slug,
'locale' => app()->getLocale(),
'channel' => core()->getCurrentChannelCode(),
@ -236,7 +236,7 @@ class ProductRepository extends Repository
*/
public function findBySlug($slug)
{
return app('Webkul\Product\Repositories\ProductFlatRepository')->findOneWhere([
return app(ProductFlatRepository::class)->findOneWhere([
'url_key' => $slug,
'locale' => app()->getLocale(),
'channel' => core()->getCurrentChannelCode(),
@ -250,7 +250,7 @@ class ProductRepository extends Repository
*/
public function getNewProducts()
{
$results = app('Webkul\Product\Repositories\ProductFlatRepository')->scopeQuery(function($query) {
$results = app(ProductFlatRepository::class)->scopeQuery(function($query) {
$channel = request()->get('channel') ?: (core()->getCurrentChannelCode() ?: core()->getDefaultChannelCode());
$locale = request()->get('locale') ?: app()->getLocale();
@ -275,7 +275,7 @@ class ProductRepository extends Repository
*/
public function getFeaturedProducts()
{
$results = app('Webkul\Product\Repositories\ProductFlatRepository')->scopeQuery(function($query) {
$results = app(ProductFlatRepository::class)->scopeQuery(function($query) {
$channel = request()->get('channel') ?: (core()->getCurrentChannelCode() ?: core()->getDefaultChannelCode());
$locale = request()->get('locale') ?: app()->getLocale();
@ -300,7 +300,7 @@ class ProductRepository extends Repository
*/
public function searchProductByAttribute($term)
{
$results = app('Webkul\Product\Repositories\ProductFlatRepository')->scopeQuery(function($query) use($term) {
$results = app(ProductFlatRepository::class)->scopeQuery(function($query) use($term) {
$channel = request()->get('channel') ?: (core()->getCurrentChannelCode() ?: core()->getDefaultChannelCode());
$locale = request()->get('locale') ?: app()->getLocale();

View File

@ -167,7 +167,9 @@ abstract class AbstractType
$product->update($data);
foreach ($product->attribute_family->custom_attributes as $attribute) {
if ($attribute->type == 'boolean') {
$route = request()->route() ? request()->route()->getName() : "";
if ($attribute->type == 'boolean' && $route != 'admin.catalog.products.massupdate') {
$data[$attribute->code] = isset($data[$attribute->code]) && $data[$attribute->code] ? 1 : 0;
}
@ -175,7 +177,7 @@ abstract class AbstractType
continue;
}
if ($attribute->type == 'date' && $data[$attribute->code] == '') {
if ($attribute->type == 'date' && $data[$attribute->code] == '' && $route != 'admin.catalog.products.massupdate') {
$data[$attribute->code] = null;
}

View File

@ -47,7 +47,7 @@ class DownloadableProductController extends Controller
/**
* Display a listing of the resource.
*
* @return \Illuminate\View\View
* @return \Illuminate\View\View
*/
public function index() {
return view($this->_config['view']);
@ -77,7 +77,7 @@ class DownloadableProductController extends Controller
}
$remainingDownloads = $downloadableLinkPurchased->download_bought - ($downloadableLinkPurchased->download_used + 1);
if ($downloadableLinkPurchased->download_bought) {
$this->downloadableLinkPurchasedRepository->update([
'download_used' => $downloadableLinkPurchased->download_used + 1,

View File

@ -25,7 +25,7 @@
<div class="item mt-5">
<div class="item-image" style="margin-right: 15px;">
<a href="{{ url()->to('/').'/products/'.$item->product->url_key }}"><img src="{{ $productBaseImage['medium_image_url'] }}" /></a>
<a href="{{ route('shop.productOrCategory.index', $item->product->url_key) }}"><img src="{{ $productBaseImage['medium_image_url'] }}" /></a>
</div>
<div class="item-details">
@ -33,7 +33,7 @@
{!! view_render_event('bagisto.shop.checkout.cart.item.name.before', ['item' => $item]) !!}
<div class="item-title">
<a href="{{ url()->to('/').'/products/'.$item->product->url_key }}">
<a href="{{ route('shop.productOrCategory.index', $item->product->url_key) }}">
{{ $item->product->name }}
</a>
</div>

View File

@ -36,13 +36,13 @@
<div class="media-info">
<?php $image = $productImageHelper->getProductBaseImage($review->product); ?>
<a href="{{ url()->to('/').'/products/'.$review->product->url_key }}" title="{{ $review->product->name }}">
<a href="{{ route('shop.productOrCategory.index', $review->product->url_key) }}" title="{{ $review->product->name }}">
<img class="media" src="{{ $image['small_image_url'] }}"/>
</a>
<div class="info">
<div class="product-name">
<a href="{{ url()->to('/').'/products/'.$review->product->url_key }}" title="{{ $review->product->name }}">
<a href="{{ route('shop.productOrCategory.index', $review->product->url_key) }}" title="{{ $review->product->name }}">
{{$review->product->name}}
</a>
</div>

View File

@ -19,21 +19,21 @@
@else
<td>{{ $attribute['admin_name'] }}</td>
@endif
@if ($attribute['type'] == 'file' && $attribute['value'])
<td>
<a href="{{ route('shop.product.file.download', [$product->product_id, $attribute['id']])}}">
<i class="icon sort-down-icon download"></i>
</a>
</td>
@elseif ($attribute['type'] == 'image' && $attribute['value'])
<td>
<a href="{{ route('shop.product.file.download', [$product->product_id, $attribute['id']])}}">
<img src="{{ Storage::url($attribute['value']) }}" style="height: 20px; width: 20px;"/>
</a>
</td>
@else
<td>{{ $attribute['value'] }}</td>
@endif
@if ($attribute['type'] == 'file' && $attribute['value'])
<td>
<a href="{{ route('shop.product.file.download', [$product->product_id, $attribute['id']])}}">
<i class="icon sort-down-icon download"></i>
</a>
</td>
@elseif ($attribute['type'] == 'image' && $attribute['value'])
<td>
<a href="{{ route('shop.product.file.download', [$product->product_id, $attribute['id']])}}">
<img src="{{ Storage::url($attribute['value']) }}" style="height: 20px; width: 20px;"/>
</a>
</td>
@else
<td>{{ $attribute['value'] }}</td>
@endif
</tr>
@endforeach

View File

@ -59,6 +59,10 @@
data-method="{{ $action['method'] }}"
data-action="{{ route($action['route'], $record->{$index}) }}"
data-token="{{ csrf_token() }}"
@if (isset($action['target']))
target="{{ $action['target'] }}"
@endif
@if (isset($action['title']))
title="{{ $action['title'] }}"

View File

@ -20,10 +20,8 @@
<script>
function finish() {
lastIndex = window.location.href.lastIndexOf("/");
secondlast = window.location.href.slice(0, lastIndex).lastIndexOf("/");
next = window.location.href.slice(0, secondlast);
next = window.location.href.split("/installer")[0];
next = next.concat('/admin/login');
window.location.href = next;
}
</script>
</script>

View File

@ -0,0 +1,113 @@
<?php
namespace Tests\Functional\Product;
use FunctionalTester;
use Faker\Factory;
use Webkul\Attribute\Models\Attribute;
use Webkul\Attribute\Models\AttributeFamily;
use Webkul\Attribute\Models\AttributeOption;
use Webkul\Core\Models\Locale;
use Webkul\Product\Models\Product;
use Webkul\Product\Models\ProductAttributeValue;
class ProductCest
{
/** @var Factory $faker */
private $faker;
/** @var Attribute $attributeBrand */
private $attributeBrand;
/** @var AttributeOption $attributeBrandDefaultOption */
private $attributeBrandDefaultOption;
/** @var AttributeOption $attributeBrandOption */
private $attributeBrandOption;
public function _before(FunctionalTester $I)
{
$this->faker = Factory::create();
$this->attributeBrand = $I->grabRecord(Attribute::class, [
'code' => 'brand',
'admin_name' => 'Brand',
]);
$locales = Locale::pluck('code')->all();
$defaultAttributeOptionAttributes = [
'attribute_id' => $this->attributeBrand->id,
'admin_name' => 'no-brand',
'sort_order' => 0,
];
foreach ($locales as $locale) {
$defaultAttributeOptionAttributes[$locale] = [
'label' => '',
];
}
$this->attributeBrandDefaultOption = $I->have(AttributeOption::class,
$defaultAttributeOptionAttributes);
$this->attributeBrandOption = $I->have(AttributeOption::class, [
'attribute_id' => $this->attributeBrand->id,
]);
}
public function selectEmptyAttributeOptionOnProductCreation(FunctionalTester $I)
{
$I->loginAsAdmin();
$I->amOnAdminRoute('admin.catalog.products.create');
$I->see(__('admin::app.catalog.products.add-title'), 'h1');
$I->selectOption('select#type', 'simple');
$attributeFamily = $I->grabRecord(AttributeFamily::class, [
'code' => 'default',
]);
$I->selectOption('select#attribute_family_id', $attributeFamily->id);
$sku = $this->faker->randomNumber(3);
$I->fillField('sku', $sku);
$I->click(__('admin::app.catalog.products.save-btn-title'));
$I->seeInSource('Product created successfully.');
$I->seeCurrentRouteIs('admin.catalog.products.edit');
$productTitle = $this->faker->word;
$productUrlKey = $this->faker->slug;
$I->fillField('name', $productTitle);
$I->fillField('url_key', $productUrlKey);
$I->selectOption($this->attributeBrand->code,
$this->attributeBrandDefaultOption->id);
$I->fillField('price', $this->faker->randomFloat(2));
$I->fillField('weight', $this->faker->randomDigit);
$I->fillField('#short_description', $this->faker->paragraph(1, true));
$I->fillField('#description', $this->faker->paragraph(5, true));
$I->click(__('admin::app.catalog.products.save-btn-title'));
$I->seeInSource('Product updated successfully.');
$I->seeCurrentRouteIs('admin.catalog.products.index');
$product = $I->grabRecord(Product::class, [
'sku' => $sku,
'type' => 'simple',
'attribute_family_id' => $attributeFamily->id,
]);
$I->seeRecord(ProductAttributeValue::class, [
'product_id' => $product->id,
'attribute_id' => $this->attributeBrand->id,
'integer_value' => $this->attributeBrandDefaultOption->id,
'text_value' => null,
]);
}
}