ConfigControllerTest.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. <?php
  2. namespace Tests\Feature;
  3. use App\Models\AdminPermission;
  4. use App\Models\AdminRole;
  5. use App\Models\Config;
  6. use App\Models\ConfigCategory;
  7. use App\Models\VueRouter;
  8. use Tests\AdminTestCase;
  9. use Illuminate\Foundation\Testing\WithFaker;
  10. use Illuminate\Foundation\Testing\RefreshDatabase;
  11. use Tests\Traits\RequestActions;
  12. class ConfigControllerTest extends AdminTestCase
  13. {
  14. use RefreshDatabase;
  15. use RequestActions;
  16. protected $resourceName = 'configs';
  17. protected function setUp(): void
  18. {
  19. parent::setUp();
  20. $this->login();
  21. }
  22. protected function getConfig(string $config)
  23. {
  24. return $this->get(route("admin.configs.{$config}"));
  25. }
  26. /**
  27. * 构建一个简单的嵌套路由
  28. * [
  29. * ['id' => 1],
  30. * [
  31. * 'id' => 2,
  32. * 'children' => ['id' => 3],
  33. * ],
  34. * [
  35. * 'id' => 4,
  36. * 'children' => ['id' => 5],
  37. * ],
  38. * ]
  39. *
  40. * @return array $ids
  41. */
  42. protected function prepareVueRouters()
  43. {
  44. $ids = factory(VueRouter::class, 5)->create()->pluck('id');
  45. VueRouter::find($ids[1])->children()->save(VueRouter::find($ids[2]));
  46. VueRouter::find($ids[3])->children()->save(VueRouter::find($ids[4]));
  47. return $ids;
  48. }
  49. public function testVueRoutersWithoutAuth()
  50. {
  51. $this->prepareVueRouters();
  52. $res = $this->getConfig('vue-routers');
  53. $res->assertStatus(200)
  54. ->assertJsonCount(3);
  55. }
  56. public function testVueRoutersUserNoAuth()
  57. {
  58. $ids = $this->prepareVueRouters();
  59. // 绑定角色
  60. VueRouter::find($ids[0])->roles()->create(
  61. factory(AdminRole::class)->create(['slug' => 'role-router-1'])->toArray()
  62. );
  63. // 子菜单绑定权限
  64. VueRouter::find($ids[2])->update([
  65. 'permission' => factory(AdminPermission::class)->create(['slug' => 'perm-router-3'])->slug,
  66. ]);
  67. $res = $this->getConfig('vue-routers');
  68. $res->assertStatus(200)
  69. ->assertJsonCount(2)
  70. ->assertJsonMissing(['id' => $ids[2]]);
  71. }
  72. public function testVueRoutersUserHasAuth()
  73. {
  74. $this->prepareVueRouters();
  75. $this->user->roles()->attach(1);
  76. $this->user->permissions()->attach(1);
  77. $res = $this->getConfig('vue-routers');
  78. $res->assertStatus(200)
  79. ->assertJsonCount(3);
  80. }
  81. public function testDestroy()
  82. {
  83. factory(Config::class)->create();
  84. $res = $this->destroyResource(1);
  85. $res->assertStatus(204);
  86. $this->assertDatabaseMissing('configs', ['id' => 1]);
  87. }
  88. public function testEdit()
  89. {
  90. $id = factory(Config::class)->create()->id;
  91. $res = $this->editResource($id);
  92. $res->assertStatus(200);
  93. }
  94. public function testUpdate()
  95. {
  96. $categoryId = factory(ConfigCategory::class)->create()->id;
  97. $configId = factory(Config::class)->create([
  98. 'name' => 'name',
  99. 'slug' => 'slug',
  100. 'type' => Config::TYPE_INPUT,
  101. ])->id;
  102. // category_id exists
  103. $res = $this->updateResource($configId, [
  104. 'category_id' => -1,
  105. ]);
  106. $res->assertStatus(422)
  107. ->assertJsonValidationErrors(['category_id']);
  108. // name unique 排除自身
  109. $res = $this->updateResource($configId, [
  110. 'name' => 'name1',
  111. ]);
  112. $res->assertStatus(201)
  113. ->assertJsonMissingValidationErrors(['name']);
  114. // type, slug 不能修改
  115. $inputs = [
  116. 'name' => 'new name',
  117. 'type' => Config::TYPE_TEXTAREA,
  118. 'slug' => 'new slug',
  119. 'category_id' => $categoryId,
  120. 'desc' => 'new desc',
  121. 'value' => 'new value',
  122. 'validation_rules' => 'new rules',
  123. ];
  124. $res = $this->updateResource($configId, $inputs);
  125. $res->assertStatus(201);
  126. $expectData = array_merge($inputs, [
  127. 'type' => Config::TYPE_TEXTAREA,
  128. 'slug' => 'new slug',
  129. 'value' => json_encode('new value'),
  130. ]);
  131. $this->assertDatabaseHas('configs', $expectData);
  132. }
  133. public function testIndex()
  134. {
  135. factory(ConfigCategory::class, 2)->create()
  136. ->each(function (ConfigCategory $cate) {
  137. $cate->configs()->createMany(factory(Config::class, 2)->make()->toArray());
  138. });
  139. $res = $this->getResources();
  140. $res->assertStatus(200)
  141. ->assertJsonCount(4, 'data');
  142. }
  143. public function testStoreValidation()
  144. {
  145. factory(ConfigCategory::class)->create();
  146. factory(Config::class)->create([
  147. 'name' => 'name',
  148. 'slug' => 'slug',
  149. ]);
  150. // type, name, slug required
  151. // category_id required
  152. // desc, validation_rules string
  153. $res = $this->storeResource([
  154. 'desc' => [],
  155. 'validation_rules' => [],
  156. ]);
  157. $res->assertStatus(422)
  158. ->assertJsonValidationErrors([
  159. 'type', 'name', 'slug', 'desc',
  160. 'validation_rules', 'category_id',
  161. ]);
  162. // type in
  163. // category_id exists
  164. // name, slug string
  165. // desc, validation_rules max:xx
  166. $res = $this->storeResource([
  167. 'type' => 'not in',
  168. 'category_id' => '-999',
  169. 'name' => [],
  170. 'slug' => [],
  171. 'desc' => str_repeat('a', 256),
  172. 'validation_rules' => str_repeat('a', 256),
  173. ]);
  174. $res->assertStatus(422)
  175. ->assertJsonValidationErrors([
  176. 'type', 'name', 'slug', 'desc', 'validation_rules',
  177. ]);
  178. // name, slug max:50
  179. $res = $this->storeResource([
  180. 'type' => Config::TYPE_INPUT,
  181. 'name' => str_repeat('a', 51),
  182. 'slug' => str_repeat('a', 51),
  183. ]);
  184. $res->assertStatus(422)
  185. ->assertJsonValidationErrors(['name', 'slug']);
  186. // name, slug unique
  187. $res = $this->storeResource([
  188. 'type' => Config::TYPE_INPUT,
  189. 'name' => 'name',
  190. 'slug' => 'slug',
  191. ]);
  192. $res->assertStatus(422)
  193. ->assertJsonValidationErrors(['name', 'slug']);
  194. }
  195. public function testConfigOptionsValidation()
  196. {
  197. // type 字段无效时,不验证
  198. $res = $this->storeResource([
  199. 'options' => null,
  200. ]);
  201. $res->assertJsonMissingValidationErrors(['options']);
  202. // options 只能为空的类型
  203. foreach ([Config::TYPE_INPUT, Config::TYPE_TEXTAREA, Config::TYPE_OTHER] as $type) {
  204. $res = $this->storeResource([
  205. 'type' => $type,
  206. 'options' => 'not null',
  207. ]);
  208. $res->assertJsonValidationErrors(['options']);
  209. }
  210. /**
  211. * type TYPE_FILE 的数据
  212. * [
  213. * 'max' => 'required|between:1,99',
  214. * 'ext' => 'nullable',
  215. * ]
  216. */
  217. $optionsInputs = [null, 'not number', '-1'];
  218. foreach ($optionsInputs as $max) {
  219. $res = $this->storeResource([
  220. 'type' => Config::TYPE_FILE,
  221. 'options' => [
  222. 'max' => $max,
  223. 'ext' => null,
  224. ],
  225. ]);
  226. $res->assertStatus(422)
  227. ->assertJsonValidationErrors('options');
  228. }
  229. /**
  230. * type TYPE_SINGLE_SELECT 或 TYPE_MULTIPLE_SELECT 的数据
  231. * [
  232. * 'options' => 'required|ConfigSelectTypeOptions',
  233. * 'type' => 'required|in:input,select',
  234. * ]
  235. */
  236. foreach ([null, [], "=>\n=>"] as $options) {
  237. $res = $this->storeResource([
  238. 'type' => Config::TYPE_SINGLE_SELECT,
  239. 'options' => [
  240. 'options' => $options,
  241. 'type' => 'input',
  242. ],
  243. ]);
  244. $res->assertStatus(422)
  245. ->assertJsonValidationErrors('options');
  246. }
  247. foreach ([null, 'not in'] as $type) {
  248. $res = $this->storeResource([
  249. 'type' => Config::TYPE_SINGLE_SELECT,
  250. 'options' => [
  251. 'options' => '1=>value1',
  252. 'type' => $type,
  253. ],
  254. ]);
  255. $res->assertStatus(422)
  256. ->assertJsonValidationErrors('options');
  257. }
  258. }
  259. public function testStore()
  260. {
  261. $categoryId = factory(ConfigCategory::class)->create()->id;
  262. $inputs = factory(Config::class)->make()->toArray();
  263. $inputs['category_id'] = $categoryId;
  264. $res = $this->storeResource($inputs);
  265. $res->assertStatus(201);
  266. $this->assertDatabaseHas('configs', [
  267. 'id' => $this->getLastInsertId('configs'),
  268. 'category_id' => $categoryId,
  269. ]);
  270. }
  271. public function testGetByCategorySlug()
  272. {
  273. $category = factory(ConfigCategory::class)->create();
  274. factory(Config::class, 2)->create(['category_id' => $category->id]);
  275. $res = $this->get(route('admin.configs.by_category_slug', [
  276. 'categorySlug' => $category->slug,
  277. ]));
  278. $res->assertStatus(200)
  279. ->assertJsonCount(2);
  280. $res = $this->get(route('admin.configs.by_category_slug', [
  281. 'categorySlug' => 'not exists slug',
  282. ]));
  283. $res->assertStatus(200)
  284. ->assertJsonCount(0);
  285. }
  286. public function testUpdateValues()
  287. {
  288. $category = factory(ConfigCategory::class)->create();
  289. factory(Config::class)->create([
  290. 'slug' => 'field',
  291. 'validation_rules' => 'required|max:20',
  292. 'category_id' => $category->id,
  293. ]);
  294. $res = $this->put(route('admin.configs.update_values'), [
  295. 'field' => null,
  296. ]);
  297. $res->assertStatus(422)
  298. ->assertJsonValidationErrors(['field']);
  299. $res = $this->put(route('admin.configs.update_values'), [
  300. 'field' => 'new value',
  301. ]);
  302. $res->assertStatus(201);
  303. $this->assertDatabaseHas('configs', [
  304. 'slug' => 'field',
  305. 'value' => json_encode('new value'),
  306. ]);
  307. }
  308. public function testGetValuesByCategorySlug()
  309. {
  310. $category = factory(ConfigCategory::class)->create(['slug' => 'slug']);
  311. factory(Config::class)->create([
  312. 'slug' => 'field',
  313. 'type' => Config::TYPE_FILE,
  314. 'category_id' => $category->id,
  315. 'value' => 'uploads/test/logo.png',
  316. ]);
  317. $res = $this->get(route('admin.configs.values.by_category_slug', [
  318. 'categorySlug' => 'slug',
  319. ]));
  320. $res->assertStatus(200)
  321. ->assertJson([
  322. 'field' => 'uploads/test/logo.png',
  323. ]);
  324. }
  325. }