Skip to content
This repository was archived by the owner on Nov 8, 2022. It is now read-only.

refactor(article-tags): rewrite ... #363

Merged
merged 17 commits into from
May 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cover/excoveralls.json

Large diffs are not rendered by default.

16 changes: 5 additions & 11 deletions docs/testing/unit-testing.zh-CN.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

### 单元测试

单元测试部分全部位于 `test/groupher_server/` 目录下, 按照接口的 Context 分为
Expand All @@ -7,13 +6,13 @@
accounts billing cms delivery logs seeds statistics
```

> Phoenix 使用 ExUnit(link) 作为测试模块,测试文件必须以 '_test.exs' 作为结尾,否则会被忽略。
> Phoenix 使用 ExUnit(link) 作为测试模块,测试文件必须以 '\_test.exs' 作为结尾,否则会被忽略。

#### 运行测试

在项目根目录执行 `make test` 即可运行所有测试, 你也可以使用 `make test.watch` 或
`make test.watch.wip` 以 watch mode 运行全部或其中一部分测试。 更多命令可以使用
`make test.help` 查看:
`make test.help` 查看:

```text

Expand All @@ -38,7 +37,7 @@ accounts billing cms delivery logs seeds statistics

#### Helper 函数

以一个实际例子作为说明:
以一个实际例子作为说明:

```elixir
defmodule GroupherServer.Test.CMS do
Expand All @@ -60,9 +59,9 @@ defmodule GroupherServer.Test.CMS do

describe "[cms tag]" do
test "create tag with valid data", ~m(community user)a do
valid_attrs = mock_attrs(:tag)
valid_attrs = mock_attrs(:article_tag)

{:ok, tag} = CMS.create_tag(community, :post, valid_attrs, %User{id: user.id})
{:ok, tag} = CMS.create_article_tag(community, :post, valid_attrs, %User{id: user.id})
assert tag.title == valid_attrs.title
end
end
Expand All @@ -81,8 +80,3 @@ use GroupherServer.TestTools
3. 这里测试的都是 `lib/groupher_server` 下的模块,不涉及 Graphql

4. 更多的技巧你可以参照文档或现有的测试用例,通常它们都浅显易懂。





3 changes: 2 additions & 1 deletion lib/groupher_server/accounts/delegates/collect_folder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,8 @@ defmodule GroupherServer.Accounts.Delegate.CollectFolder do

query
|> filter_thread_ifneed(filter)
|> QueryBuilder.filter_pack(filter)
# delete thread in filter for now, otherwise it will crash querybuilder, because thread not exsit on CollectFolder
|> QueryBuilder.filter_pack(filter |> Map.delete(:thread))
|> ORM.paginater(page: page, size: size)
|> done()
end
Expand Down
43 changes: 43 additions & 0 deletions lib/groupher_server/cms/article_tag.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
defmodule GroupherServer.CMS.ArticleTag do
@moduledoc false
alias __MODULE__

use Ecto.Schema
use Accessible

import Ecto.Changeset

alias GroupherServer.CMS
alias CMS.{Author, Community}

@required_fields ~w(thread title color author_id community_id)a
@updatable_fields ~w(thread title color community_id group)a

@type t :: %ArticleTag{}
schema "article_tags" do
field(:title, :string)
field(:color, :string)
field(:thread, :string)
field(:group, :string)

belongs_to(:community, Community)
belongs_to(:author, Author)

timestamps(type: :utc_datetime)
end

def changeset(%ArticleTag{} = tag, attrs) do
tag
|> cast(attrs, @required_fields ++ @updatable_fields)
|> validate_required(@required_fields)
|> foreign_key_constraint(:user_id)
|> foreign_key_constraint(:community_id)
end

def update_changeset(%ArticleTag{} = tag, attrs) do
tag
|> cast(attrs, @updatable_fields)
|> foreign_key_constraint(:user_id)
|> foreign_key_constraint(:community_id)
end
end
11 changes: 9 additions & 2 deletions lib/groupher_server/cms/cms.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ defmodule GroupherServer.CMS do
ArticleUpvote,
ArticleCommentAction,
ArticleCommentEmotion,
ArticleTag,
CommentCURD,
CommunitySync,
CommunityCURD,
Expand All @@ -43,10 +44,16 @@ defmodule GroupherServer.CMS do
defdelegate create_thread(attrs), to: CommunityCURD
defdelegate count(community, part), to: CommunityCURD
# >> tag
defdelegate create_article_tag(community, thread, attrs, user), to: ArticleTag
defdelegate update_article_tag(tag_id, attrs), to: ArticleTag
defdelegate delete_article_tag(tag_id), to: ArticleTag
defdelegate set_article_tag(thread, article_id, tag_id), to: ArticleTag
defdelegate unset_article_tag(thread, article_id, tag_id), to: ArticleTag
defdelegate paged_article_tags(filter), to: ArticleTag

defdelegate create_tag(community, thread, attrs, user), to: CommunityCURD
defdelegate update_tag(attrs), to: CommunityCURD
defdelegate get_tags(community, thread), to: CommunityCURD
defdelegate get_tags(filter), to: CommunityCURD

# >> wiki & cheatsheet (sync with github)
defdelegate get_wiki(community), to: CommunitySync
defdelegate get_cheatsheet(community), to: CommunitySync
Expand Down
2 changes: 1 addition & 1 deletion lib/groupher_server/cms/delegates/abuse_report.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ defmodule GroupherServer.CMS.Delegate.AbuseReport do
alias GroupherServer.{Accounts, CMS, Repo}

alias Accounts.User
alias CMS.{Community, AbuseReport, ArticleComment, Embeds}
alias CMS.{AbuseReport, ArticleComment, Embeds}

alias Ecto.Multi

Expand Down
43 changes: 1 addition & 42 deletions lib/groupher_server/cms/delegates/article_community.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleCommunity do
alias Helper.Types, as: T
alias Helper.ORM

alias GroupherServer.CMS.{Embeds, Community, Tag, PinnedArticle}
alias GroupherServer.CMS.{Embeds, Community, PinnedArticle}
alias GroupherServer.Repo

alias Ecto.Multi
Expand Down Expand Up @@ -128,47 +128,6 @@ defmodule GroupherServer.CMS.Delegate.ArticleCommunity do
defp result({:ok, %{mirror_target_community: result}}), do: result |> done()
defp result({:error, _, result, _steps}), do: {:error, result}

@doc """
set general tag for post / tuts ...
"""
# check community first
def set_tag(thread, %Tag{id: tag_id}, content_id) do
with {:ok, action} <- match_action(thread, :tag),
{:ok, content} <- ORM.find(action.target, content_id, preload: :tags),
{:ok, tag} <- ORM.find(action.reactor, tag_id) do
update_content_tag(content, tag)

# NOTE: this should be control by Middleware
# case tag_in_community_thread?(%Community{id: communitId}, thread, tag) do
# true ->
# content
# |> Ecto.Changeset.change()
# |> Ecto.Changeset.put_assoc(:tags, content.tags ++ [tag])
# |> Repo.update()

# _ ->
# {:error, message: "Tag,Community,Thread not match", code: ecode(:custom)}
# end
end
end

def unset_tag(thread, %Tag{id: tag_id}, content_id) do
with {:ok, action} <- match_action(thread, :tag),
{:ok, content} <- ORM.find(action.target, content_id, preload: :tags),
{:ok, tag} <- ORM.find(action.reactor, tag_id) do
update_content_tag(content, tag, :drop)
end
end

defp update_content_tag(content, %Tag{} = tag, opt \\ :add) do
new_tags = if opt == :add, do: content.tags ++ [tag], else: content.tags -- [tag]

content
|> Ecto.Changeset.change()
|> Ecto.Changeset.put_assoc(:tags, new_tags)
|> Repo.update()
end

@doc "update isEdited meta label if needed"
# TODO: diff history
def update_edit_status(%{meta: %Embeds.ArticleMeta{is_edited: false} = meta} = content) do
Expand Down
61 changes: 11 additions & 50 deletions lib/groupher_server/cms/delegates/article_curd.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
import Ecto.Query, warn: false

import GroupherServer.CMS.Helper.Matcher2
import GroupherServer.CMS.Helper.Matcher, only: [match_action: 2]

import Helper.Utils,
only: [done: 1, pick_by: 2, integerfy: 1, strip_struct: 1, module_to_thread: 1]
Expand All @@ -18,9 +17,9 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
alias GroupherServer.{Accounts, CMS, Delivery, Email, Repo, Statistics}

alias Accounts.User
alias CMS.{Author, Community, PinnedArticle, Embeds, Delegate, Tag}
alias CMS.{Author, Community, PinnedArticle, Embeds, Delegate}

alias Delegate.ArticleCommunity
alias Delegate.{ArticleCommunity, ArticleTag}

alias Ecto.Multi

Expand Down Expand Up @@ -71,7 +70,6 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do

with {:ok, info} <- match(thread) do
info.model
# TODO: trash -> mark_delete
|> domain_filter_query(filter)
|> QueryBuilder.filter_pack(Map.merge(filter, %{mark_delete: false}))
|> ORM.paginater(~m(page size)a)
Expand Down Expand Up @@ -125,17 +123,17 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
"""
def create_article(%Community{id: cid}, thread, attrs, %User{id: uid}) do
with {:ok, author} <- ensure_author_exists(%User{id: uid}),
{:ok, action} <- match_action(thread, :community),
{:ok, info} <- match(thread),
{:ok, community} <- ORM.find(Community, cid) do
Multi.new()
|> Multi.run(:create_article, fn _, _ ->
do_create_article(action.target, attrs, author, community)
do_create_article(info.model, attrs, author, community)
end)
|> Multi.run(:mirror_article, fn _, %{create_article: article} ->
ArticleCommunity.mirror_article(thread, article.id, community.id)
end)
|> Multi.run(:set_tag, fn _, %{create_article: article} ->
exec_set_tag(thread, article.id, attrs)
|> Multi.run(:set_article_tags, fn _, %{create_article: article} ->
ArticleTag.set_article_tags(community, thread, article, attrs)
end)
|> Multi.run(:mention_users, fn _, %{create_article: article} ->
Delivery.mention_from_content(community.raw, thread, article, attrs, %User{id: uid})
Expand Down Expand Up @@ -184,10 +182,6 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
|> Multi.run(:update_edit_status, fn _, %{update_article: update_article} ->
ArticleCommunity.update_edit_status(update_article)
end)
|> Multi.run(:update_tag, fn _, _ ->
# TODO: move it to ArticleCommunity module
exec_update_tags(article, args)
end)
|> Repo.transaction()
|> update_article_result()
end
Expand Down Expand Up @@ -316,7 +310,9 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
defp add_pin_articles_ifneed(articles, _querable, _filter), do: articles

# if filter contains like: tags, sort.., then don't add pin article
defp should_add_pin?(%{page: 1, tag: :all, sort: :desc_inserted} = _filter) do
# TODO: tag
# defp should_add_pin?(%{page: 1, article_tag: :all, sort: :desc_inserted} = _filter) do
defp should_add_pin?(%{page: 1, sort: :desc_inserted} = _filter) do
{:ok, :pass}
end

Expand Down Expand Up @@ -366,7 +362,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
{:error, [message: "set community flag", code: ecode(:create_fails)]}
end

defp create_article_result({:error, :set_tag, result, _steps}) do
defp create_article_result({:error, :set_article_tags, result, _steps}) do
{:error, result}
end

Expand All @@ -386,43 +382,9 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
|> Repo.insert()
end

defp exec_set_tag(thread, id, %{tags: tags}) do
try do
Enum.each(tags, fn tag ->
{:ok, _} = ArticleCommunity.set_tag(thread, %Tag{id: tag.id}, id)
end)

{:ok, "psss"}
rescue
_ -> {:error, [message: "set tag", code: ecode(:create_fails)]}
end
end

defp exec_set_tag(_thread, _id, _attrs), do: {:ok, :pass}

# except Job, other article will just pass, should use set_tag function instead
# except Job, other article will just pass, should use set_article_tags function instead
# defp exec_update_tags(_, _tags_ids), do: {:ok, :pass}

defp exec_update_tags(_article, %{tags: tags_ids}) when tags_ids == [], do: {:ok, :pass}

defp exec_update_tags(article, %{tags: tags_ids}) do
with {:ok, article} <- ORM.find(article.__struct__, article.id, preload: :tags) do
tags =
Enum.reduce(tags_ids, [], fn t, acc ->
{:ok, tag} = ORM.find(Tag, t.id)

acc ++ [tag]
end)

article
|> Ecto.Changeset.change()
|> Ecto.Changeset.put_assoc(:tags, tags)
|> Repo.update()
end
end

defp exec_update_tags(_article, _), do: {:ok, :pass}

defp update_viewed_user_list(%{meta: nil} = article, user_id) do
new_ids = Enum.uniq([user_id] ++ @default_article_meta.viewed_user_ids)
meta = @default_article_meta |> Map.merge(%{viewed_user_ids: new_ids})
Expand All @@ -446,7 +408,6 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do

defp update_article_result({:ok, %{update_edit_status: result}}), do: {:ok, result}
defp update_article_result({:error, :update_article, result, _steps}), do: {:error, result}
defp update_article_result({:error, :update_tag, result, _steps}), do: {:error, result}

defp read_result({:ok, %{inc_views: result}}), do: result |> done()

Expand Down
Loading