diff --git a/Makefile b/Makefile index 425a392f9..6aee8aaf4 100644 --- a/Makefile +++ b/Makefile @@ -167,7 +167,8 @@ test.watch: mix test.watch test.watch.wip: # work around, see: https://elixirforum.com/t/mix-test-file-watch/12298/2 - mix test --listen-on-stdin --stale --trace --only wip + # mix test --listen-on-stdin --stale --trace --only wip + mix test --listen-on-stdin --stale --only wip # test.watch not work now, see: https://github.com/lpil/mix-test.watch/issues/116 # mix test.watch --only wip --stale test.watch.wip2: diff --git a/config/config.exs b/config/config.exs index 1a8e4ef58..e76d73aad 100644 --- a/config/config.exs +++ b/config/config.exs @@ -63,6 +63,14 @@ config :groupher_server, :customization, config :groupher_server, :article, # NOTE: do not change unless you know what you are doing article_threads: [:post, :job, :repo], + # in this period, paged articles will sort front if non-article-author commented + # 在此时间段内,一旦有非文章作者的用户评论,该文章就会排到前面 + active_period_days: %{ + post: 10, + job: 10, + repo: 10 + }, + # NOTE: if you want to add/remove emotion, just edit the list below # and migrate the field to table "articles_users_emotions" supported_emotions: [ diff --git a/lib/groupher_server/cms/cms.ex b/lib/groupher_server/cms/cms.ex index 2afcb903c..0c141f08d 100644 --- a/lib/groupher_server/cms/cms.ex +++ b/lib/groupher_server/cms/cms.ex @@ -93,6 +93,10 @@ defmodule GroupherServer.CMS do defdelegate mark_delete_article(thread, id), to: ArticleCURD defdelegate undo_mark_delete_article(thread, id), to: ArticleCURD + defdelegate update_active_timestamp(thread, article), to: ArticleCURD + defdelegate sink_article(thread, id), to: ArticleCURD + defdelegate undo_sink_article(thread, id), to: ArticleCURD + defdelegate upvote_article(thread, article_id, user), to: ArticleUpvote defdelegate undo_upvote_article(thread, article_id, user), to: ArticleUpvote @@ -112,7 +116,7 @@ defmodule GroupherServer.CMS do # >> set flag on article, like: pin / unpin article defdelegate pin_article(thread, id, community_id), to: ArticleCommunity defdelegate undo_pin_article(thread, id, community_id), to: ArticleCommunity - defdelegate lock_article_comment(article), to: ArticleCommunity + defdelegate lock_article_comment(thread, article_id), to: ArticleCommunity # >> community: set / unset defdelegate mirror_article(thread, article_id, community_id), to: ArticleCommunity diff --git a/lib/groupher_server/cms/delegates/article_comment.ex b/lib/groupher_server/cms/delegates/article_comment.ex index 835acc3d0..c2ee1fa0e 100644 --- a/lib/groupher_server/cms/delegates/article_comment.ex +++ b/lib/groupher_server/cms/delegates/article_comment.ex @@ -105,6 +105,12 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do |> Multi.run(:add_participator, fn _, _ -> add_participator_to_article(article, user) end) + |> Multi.run(:update_article_active_timestamp, fn _, %{create_article_comment: comment} -> + case comment.author_id == article.author.user.id do + true -> {:ok, :pass} + false -> CMS.update_active_timestamp(thread, article) + end + end) |> Repo.transaction() |> result() end @@ -284,9 +290,5 @@ defmodule GroupherServer.CMS.Delegate.ArticleComment do raise_error(:create_comment, result) end - defp result({:error, :add_participator, result, _steps}) do - {:error, result} - end - defp result({:error, _, result, _steps}), do: {:error, result} end diff --git a/lib/groupher_server/cms/delegates/article_community.ex b/lib/groupher_server/cms/delegates/article_community.ex index fc4512707..665f5578c 100644 --- a/lib/groupher_server/cms/delegates/article_community.ex +++ b/lib/groupher_server/cms/delegates/article_community.ex @@ -6,7 +6,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleCommunity do import Ecto.Query, warn: false import Helper.ErrorCode - import Helper.Utils, only: [strip_struct: 1, done: 1] + import Helper.Utils, only: [strip_struct: 1, done: 1, ensure: 2] import GroupherServer.CMS.Helper.Matcher alias Helper.Types, as: T @@ -17,6 +17,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleCommunity do alias Ecto.Multi + @default_article_meta Embeds.ArticleMeta.default_meta() @max_pinned_article_count_per_thread Community.max_pinned_article_count_per_thread() @spec pin_article(T.article_thread(), Integer.t(), Integer.t()) :: {:ok, PinnedArticle.t()} @@ -144,21 +145,16 @@ defmodule GroupherServer.CMS.Delegate.ArticleCommunity do def update_edit_status(content, _), do: {:ok, content} @doc "lock comment of a article" - # TODO: record it to ArticleLog - def lock_article_comment( - %{meta: %Embeds.ArticleMeta{is_comment_locked: false} = meta} = content - ) do - meta = - meta - |> Map.from_struct() - |> Map.delete(:id) - |> Map.merge(%{is_comment_locked: true}) + def lock_article_comment(thread, id) do + with {:ok, info} <- match(thread), + {:ok, article} <- ORM.find(info.model, id) do + article_meta = ensure(article.meta, @default_article_meta) + meta = Map.merge(article_meta, %{is_comment_locked: true}) - ORM.update_meta(content, meta) + ORM.update_meta(article, meta) + end end - def lock_article_comment(content), do: {:ok, content} - # check if the thread has aready enough pinned articles defp check_pinned_article_count(community_id, thread) do thread_upcase = thread |> to_string |> String.upcase() diff --git a/lib/groupher_server/cms/delegates/article_curd.ex b/lib/groupher_server/cms/delegates/article_curd.ex index d0ee5f017..589feaee1 100644 --- a/lib/groupher_server/cms/delegates/article_curd.ex +++ b/lib/groupher_server/cms/delegates/article_curd.ex @@ -7,7 +7,15 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do import GroupherServer.CMS.Helper.Matcher import Helper.Utils, - only: [done: 1, pick_by: 2, integerfy: 1, strip_struct: 1, module_to_thread: 1] + only: [ + done: 1, + pick_by: 2, + integerfy: 1, + strip_struct: 1, + module_to_thread: 1, + get_config: 2, + ensure: 2 + ] import GroupherServer.CMS.Delegate.Helper, only: [mark_viewer_emotion_states: 2] import Helper.ErrorCode @@ -23,6 +31,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do alias Ecto.Multi + @active_period get_config(:article, :active_period_days) @default_emotions Embeds.ArticleEmotion.default_emotions() @default_article_meta Embeds.ArticleMeta.default_meta() @@ -31,7 +40,16 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do """ def read_article(thread, id) do with {:ok, info} <- match(thread) do - ORM.read(info.model, id, inc: :views) + Multi.new() + |> Multi.run(:inc_views, fn _, _ -> ORM.read(info.model, id, inc: :views) end) + |> Multi.run(:update_article_meta, fn _, %{inc_views: article} -> + article_meta = ensure(article.meta, @default_article_meta) + meta = Map.merge(article_meta, %{can_undo_sink: in_active_period?(thread, article)}) + + ORM.update_meta(article, meta) + end) + |> Repo.transaction() + |> result() end end @@ -41,8 +59,12 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do def read_article(thread, id, %User{id: user_id}) do with {:ok, info} <- match(thread) do Multi.new() - |> Multi.run(:inc_views, fn _, _ -> - ORM.read(info.model, id, inc: :views) + |> Multi.run(:inc_views, fn _, _ -> ORM.read(info.model, id, inc: :views) end) + |> Multi.run(:update_article_meta, fn _, %{inc_views: article} -> + article_meta = ensure(article.meta, @default_article_meta) + meta = Map.merge(article_meta, %{can_undo_sink: in_active_period?(thread, article)}) + + ORM.update_meta(article, meta) end) |> Multi.run(:add_viewed_user, fn _, %{inc_views: article} -> update_viewed_user_list(article, user_id) @@ -142,6 +164,9 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do |> Multi.run(:set_article_tags, fn _, %{create_article: article} -> ArticleTag.set_article_tags(community, thread, article, attrs) end) + |> Multi.run(:set_active_at_timestamp, fn _, %{create_article: article} -> + ORM.update(article, %{active_at: article.inserted_at}) + end) |> Multi.run(:update_community_article_count, fn _, _ -> CommunityCURD.update_community_count_field(community, thread) end) @@ -156,7 +181,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do Statistics.log_publish_action(%User{id: uid}) end) |> Repo.transaction() - |> create_article_result() + |> result() end end @@ -199,6 +224,55 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do |> result() end + @doc """ + update active at timestamp of an article + """ + def update_active_timestamp(thread, article) do + # @article_active_period + # 1. 超过时限不更新 + # 2. 已经沉默的不更新, is_sinked + with true <- in_active_period?(thread, article) do + ORM.update(article, %{active_at: DateTime.utc_now()}) + else + _ -> {:ok, :pass} + end + end + + @doc """ + sink article + """ + def sink_article(thread, id) do + with {:ok, info} <- match(thread), + {:ok, article} <- ORM.find(info.model, id) do + meta = Map.merge(article.meta, %{is_sinked: true, last_active_at: article.active_at}) + ORM.update_meta(article, meta, changes: %{active_at: article.inserted_at}) + end + end + + @doc """ + undo sink article + """ + def undo_sink_article(thread, id) do + with {:ok, info} <- match(thread), + {:ok, article} <- ORM.find(info.model, id), + true <- in_active_period?(thread, article) do + meta = Map.merge(article.meta, %{is_sinked: false}) + ORM.update_meta(article, meta, changes: %{active_at: meta.last_active_at}) + else + false -> raise_error(:undo_sink_old_article, "can not undo sink old article") + end + end + + # check is an article's active_at is in active period + defp in_active_period?(thread, article) do + active_period_days = Map.get(@active_period, thread) + + inserted_at = article.inserted_at + active_threshold = Timex.shift(Timex.now(), days: -active_period_days) + + :gt == DateTime.compare(inserted_at, active_threshold) + end + @doc """ mark delete falst for an anticle """ @@ -300,7 +374,7 @@ 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, sort: :desc_inserted} = filter) do + defp should_add_pin?(%{page: 1, sort: :desc_active} = filter) do skip_pinned_fields = [:article_tag, :article_tags] not Enum.any?(Map.keys(filter), &(&1 in skip_pinned_fields)) @@ -331,35 +405,6 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do |> Map.put(:total_count, normal_count) end - defp create_article_result({:ok, %{create_article: result}}) do - Later.exec({__MODULE__, :notify_admin_new_article, [result]}) - {:ok, result} - end - - defp create_article_result({:error, :create_article, %Ecto.Changeset{} = result, _steps}) do - {:error, result} - end - - defp create_article_result({:error, :create_article, _result, _steps}) do - {:error, [message: "create cms article author", code: ecode(:create_fails)]} - end - - defp create_article_result({:error, :mirror_article, _result, _steps}) do - {:error, [message: "set community", code: ecode(:create_fails)]} - end - - defp create_article_result({:error, :set_community_flag, _result, _steps}) do - {:error, [message: "set community flag", code: ecode(:create_fails)]} - end - - defp create_article_result({:error, :set_article_tags, result, _steps}) do - {:error, result} - end - - defp create_article_result({:error, :log_action, _result, _steps}) do - {:error, [message: "log action", code: ecode(:create_fails)]} - end - # for create artilce step in Multi.new defp do_create_article(target, attrs, %Author{id: aid}, %Community{id: cid}) do target @@ -396,9 +441,32 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do end end + # create done + defp result({:ok, %{set_active_at_timestamp: result}}) do + Later.exec({__MODULE__, :notify_admin_new_article, [result]}) + {:ok, result} + end + defp result({:ok, %{update_edit_status: result}}), do: {:ok, result} defp result({:ok, %{update_article: result}}), do: {:ok, result} defp result({:ok, %{set_viewer_has_states: result}}), do: result |> done() + defp result({:ok, %{update_article_meta: result}}), do: {:ok, result} + + defp result({:error, :create_article, _result, _steps}) do + {:error, [message: "create cms article author", code: ecode(:create_fails)]} + end + + defp result({:error, :mirror_article, _result, _steps}) do + {:error, [message: "set community", code: ecode(:create_fails)]} + end + + defp result({:error, :set_community_flag, _result, _steps}) do + {:error, [message: "set community flag", code: ecode(:create_fails)]} + end + + defp result({:error, :log_action, _result, _steps}) do + {:error, [message: "log action", code: ecode(:create_fails)]} + end defp result({:error, _, result, _steps}), do: {:error, result} end diff --git a/lib/groupher_server/cms/embeds/article_meta.ex b/lib/groupher_server/cms/embeds/article_meta.ex index bddd20745..2edae013f 100644 --- a/lib/groupher_server/cms/embeds/article_meta.ex +++ b/lib/groupher_server/cms/embeds/article_meta.ex @@ -6,20 +6,23 @@ defmodule GroupherServer.CMS.Embeds.ArticleMeta do use Accessible import Ecto.Changeset - @optional_fields ~w(is_edited is_comment_locked upvoted_user_ids collected_user_ids viewed_user_ids reported_user_ids reported_count)a - - @default_meta %{ - is_edited: false, - is_comment_locked: false, - upvoted_user_ids: [], - collected_user_ids: [], - viewed_user_ids: [], - reported_user_ids: [], - reported_count: 0 - } + @optional_fields ~w(is_edited is_comment_locked upvoted_user_ids collected_user_ids viewed_user_ids reported_user_ids reported_count is_sinked can_undo_sink last_active_at)a @doc "for test usage" - def default_meta(), do: @default_meta + def default_meta() do + %{ + is_edited: false, + is_comment_locked: false, + upvoted_user_ids: [], + collected_user_ids: [], + viewed_user_ids: [], + reported_user_ids: [], + reported_count: 0, + is_sinked: false, + can_undo_sink: true, + last_active_at: nil + } + end embedded_schema do field(:is_edited, :boolean, default: false) @@ -30,6 +33,11 @@ defmodule GroupherServer.CMS.Embeds.ArticleMeta do field(:viewed_user_ids, {:array, :integer}, default: []) field(:reported_user_ids, {:array, :integer}, default: []) field(:reported_count, :integer, default: 0) + + field(:is_sinked, :boolean, default: false) + field(:can_undo_sink, :boolean, default: false) + # if undo_sink, can recover last active_at from here + field(:last_active_at, :utc_datetime_usec) end def changeset(struct, params) do diff --git a/lib/groupher_server/cms/helper/macros.ex b/lib/groupher_server/cms/helper/macros.ex index 0c5b6c67f..8889bc299 100644 --- a/lib/groupher_server/cms/helper/macros.ex +++ b/lib/groupher_server/cms/helper/macros.ex @@ -121,7 +121,8 @@ defmodule GroupherServer.CMS.Helper.Macros do :article_comments_participators_count, :upvotes_count, :collects_count, - :mark_delete + :mark_delete, + :active_at ] end @@ -189,6 +190,7 @@ defmodule GroupherServer.CMS.Helper.Macros do viewer_has_fields() article_comment_fields() + field(:active_at, :utc_datetime_usec) # TODO: # reference_articles # related_articles diff --git a/lib/groupher_server_web/middleware/pagesize_proof.ex b/lib/groupher_server_web/middleware/pagesize_proof.ex index a990486c1..196e61077 100644 --- a/lib/groupher_server_web/middleware/pagesize_proof.ex +++ b/lib/groupher_server_web/middleware/pagesize_proof.ex @@ -23,7 +23,7 @@ defmodule GroupherServerWeb.Middleware.PageSizeProof do def call( %{context: %{cur_user: %{customization: customization}}, arguments: arguments} = resolution, - _info + args ) when not is_nil(customization) do # NOTE: c11n display_density should also linted by page limit, @@ -34,8 +34,7 @@ defmodule GroupherServerWeb.Middleware.PageSizeProof do true -> filter = arguments.filter |> Map.merge(%{size: size}) arguments = arguments |> Map.merge(%{filter: filter}) - - %{resolution | arguments: sort_desc_by_default(arguments)} + %{resolution | arguments: set_sort_ifneed(arguments, args)} false -> arguments = arguments |> Map.merge(%{filter: %{page: 1, size: size, first: size}}) @@ -43,10 +42,20 @@ defmodule GroupherServerWeb.Middleware.PageSizeProof do end end - def call(resolution, _) do + def call(resolution, args) do case valid_size(resolution.arguments) do {:error, msg} -> resolution |> handle_absinthe_error(msg, ecode(:pagination)) - arguments -> %{resolution | arguments: sort_desc_by_default(arguments)} + arguments -> %{resolution | arguments: set_sort_ifneed(arguments, args)} + end + end + + defp set_sort_ifneed(%{filter: filter} = arguments, args) do + case args do + [] -> + sort_desc_by_default(arguments) + + [default_sort: :desc_active] -> + Map.merge(arguments, %{filter: Map.merge(%{sort: :desc_active}, filter)}) end end diff --git a/lib/groupher_server_web/resolvers/cms_resolver.ex b/lib/groupher_server_web/resolvers/cms_resolver.ex index 0d063c6a1..a52039c2b 100644 --- a/lib/groupher_server_web/resolvers/cms_resolver.ex +++ b/lib/groupher_server_web/resolvers/cms_resolver.ex @@ -105,6 +105,9 @@ defmodule GroupherServerWeb.Resolvers.CMS do # ####################### # thread reaction .. # ####################### + def sink_article(_root, ~m(id thread)a, _info), do: CMS.sink_article(thread, id) + def undo_sink_article(_root, ~m(id thread)a, _info), do: CMS.undo_sink_article(thread, id) + def upvote_article(_root, ~m(id thread)a, %{context: %{cur_user: user}}) do CMS.upvote_article(thread, id, user) end diff --git a/lib/groupher_server_web/schema/Helper/fields.ex b/lib/groupher_server_web/schema/Helper/fields.ex index e72b8c933..ade73a6ca 100644 --- a/lib/groupher_server_web/schema/Helper/fields.ex +++ b/lib/groupher_server_web/schema/Helper/fields.ex @@ -12,6 +12,14 @@ defmodule GroupherServerWeb.Schema.Helper.Fields do @article_threads get_config(:article, :article_threads) + defmacro timestamp_fields(:article) do + quote do + field(:inserted_at, :datetime) + field(:updated_at, :datetime) + field(:active_at, :datetime) + end + end + defmacro timestamp_fields do quote do field(:inserted_at, :datetime) diff --git a/lib/groupher_server_web/schema/Helper/mutations.ex b/lib/groupher_server_web/schema/Helper/mutations.ex index d53830fb9..e44e586cd 100644 --- a/lib/groupher_server_web/schema/Helper/mutations.ex +++ b/lib/groupher_server_web/schema/Helper/mutations.ex @@ -5,6 +5,34 @@ defmodule GroupherServerWeb.Schema.Helper.Mutations do alias GroupherServerWeb.Middleware, as: M alias GroupherServerWeb.Resolvers, as: R + defmacro article_sink_mutation(thread) do + quote do + @desc unquote("sink a #{thread}") + field unquote(:"sink_#{thread}"), :article do + arg(:id, non_null(:id)) + arg(:community_id, non_null(:id)) + arg(:thread, unquote(:"#{thread}_thread"), default_value: unquote(thread)) + + middleware(M.Authorize, :login) + middleware(M.PassportLoader, source: :community) + middleware(M.Passport, claim: unquote("cms->c?->#{to_string(thread)}.sink")) + resolve(&R.CMS.sink_article/3) + end + + @desc unquote("undo sink to #{thread}") + field unquote(:"undo_sink_#{thread}"), :article do + arg(:id, non_null(:id)) + arg(:community_id, non_null(:id)) + arg(:thread, unquote(:"#{thread}_thread"), default_value: unquote(thread)) + + middleware(M.Authorize, :login) + middleware(M.PassportLoader, source: :community) + middleware(M.Passport, claim: unquote("cms->c?->#{to_string(thread)}.undo_sink")) + resolve(&R.CMS.undo_sink_article/3) + end + end + end + defmacro article_upvote_mutation(thread) do quote do @desc unquote("upvote to #{thread}") diff --git a/lib/groupher_server_web/schema/Helper/queries.ex b/lib/groupher_server_web/schema/Helper/queries.ex index c0065b0b2..4ed41bfa6 100644 --- a/lib/groupher_server_web/schema/Helper/queries.ex +++ b/lib/groupher_server_web/schema/Helper/queries.ex @@ -62,7 +62,7 @@ defmodule GroupherServerWeb.Schema.Helper.Queries do arg(:thread, unquote(:"#{thread}_thread"), default_value: unquote(thread)) arg(:filter, non_null(unquote(:"paged_#{thread}s_filter"))) - middleware(M.PageSizeProof) + middleware(M.PageSizeProof, default_sort: :desc_active) resolve(&R.CMS.paged_articles/3) end end diff --git a/lib/groupher_server_web/schema/account/account_types.ex b/lib/groupher_server_web/schema/account/account_types.ex index 1e15ad874..b79f417ba 100644 --- a/lib/groupher_server_web/schema/account/account_types.ex +++ b/lib/groupher_server_web/schema/account/account_types.ex @@ -26,14 +26,13 @@ defmodule GroupherServerWeb.Schema.Account.Types do field(:bio, :string) field(:sex, :string) field(:email, :string) + field(:location, :string) field(:geo_city, :string) field(:views, :integer) field(:social, :social_map, resolve: dataloader(Accounts, :social)) - field(:inserted_at, :datetime) - field(:updated_at, :datetime) field(:from_github, :boolean) field(:github_profile, :github_profile, resolve: dataloader(Accounts, :github_profile)) # field(:achievement, :achievement, resolve: dataloader(Accounts, :achievement)) @@ -111,6 +110,8 @@ defmodule GroupherServerWeb.Schema.Account.Types do middleware(M.PageSizeProof) resolve(&R.Accounts.fetch_sys_notifications/3) end + + timestamp_fields() end # field(:sidebar_layout, :map) @@ -171,9 +172,9 @@ defmodule GroupherServerWeb.Schema.Account.Types do field(:total_count, :integer) field(:private, :boolean) field(:last_updated, :datetime) - field(:inserted_at, :datetime) - field(:updated_at, :datetime) field(:meta, :collect_folder_meta) + + timestamp_fields() end object :paged_collect_folders do diff --git a/lib/groupher_server_web/schema/cms/cms_metrics.ex b/lib/groupher_server_web/schema/cms/cms_metrics.ex index 6ee852a6e..7086d777c 100644 --- a/lib/groupher_server_web/schema/cms/cms_metrics.ex +++ b/lib/groupher_server_web/schema/cms/cms_metrics.ex @@ -184,13 +184,13 @@ defmodule GroupherServerWeb.Schema.CMS.Metrics do # field(:added_after, :datetime) end - @desc "article_filter doc" - input_object :paged_article_filter do - @desc "limit of records (default 20), if first > 30, only return 30 at most" - pagination_args() - article_filter_fields() - field(:sort, :sort_enum) - end + # @desc "article_filter doc" + # input_object :paged_article_filter do + # @desc "limit of records (default 20), if first > 30, only return 30 at most" + # pagination_args() + # article_filter_fields() + # field(:sort, :sort_enum) + # end @desc "posts_filter doc" input_object :paged_posts_filter do diff --git a/lib/groupher_server_web/schema/cms/cms_types.ex b/lib/groupher_server_web/schema/cms/cms_types.ex index 5a80a3ed2..dbb6c4931 100644 --- a/lib/groupher_server_web/schema/cms/cms_types.ex +++ b/lib/groupher_server_web/schema/cms/cms_types.ex @@ -100,7 +100,7 @@ defmodule GroupherServerWeb.Schema.CMS.Types do # upvoted_count # collected_count - timestamp_fields() + timestamp_fields(:article) end object :job do @@ -132,7 +132,7 @@ defmodule GroupherServerWeb.Schema.CMS.Types do # comments_participators article_comments_fields() viewer_has_state_fields() - timestamp_fields() + timestamp_fields(:article) end object :repo do @@ -175,7 +175,7 @@ defmodule GroupherServerWeb.Schema.CMS.Types do # comments_count # comments_participators - timestamp_fields() + timestamp_fields(:article) end object :repo_contributor do diff --git a/lib/groupher_server_web/schema/cms/mutations/job.ex b/lib/groupher_server_web/schema/cms/mutations/job.ex index c76190402..c2c0e8a5a 100644 --- a/lib/groupher_server_web/schema/cms/mutations/job.ex +++ b/lib/groupher_server_web/schema/cms/mutations/job.ex @@ -55,6 +55,7 @@ defmodule GroupherServerWeb.Schema.CMS.Mutations.Job do end ############# + article_sink_mutation(:job) article_upvote_mutation(:job) article_pin_mutation(:job) article_mark_delete_mutation(:job) diff --git a/lib/groupher_server_web/schema/cms/mutations/post.ex b/lib/groupher_server_web/schema/cms/mutations/post.ex index 694fdfb22..6c80201e9 100644 --- a/lib/groupher_server_web/schema/cms/mutations/post.ex +++ b/lib/groupher_server_web/schema/cms/mutations/post.ex @@ -45,6 +45,7 @@ defmodule GroupherServerWeb.Schema.CMS.Mutations.Post do end ############# + article_sink_mutation(:post) article_upvote_mutation(:post) article_pin_mutation(:post) article_mark_delete_mutation(:post) diff --git a/lib/groupher_server_web/schema/cms/mutations/repo.ex b/lib/groupher_server_web/schema/cms/mutations/repo.ex index 3478e8b61..c7776ff43 100644 --- a/lib/groupher_server_web/schema/cms/mutations/repo.ex +++ b/lib/groupher_server_web/schema/cms/mutations/repo.ex @@ -71,6 +71,7 @@ defmodule GroupherServerWeb.Schema.CMS.Mutations.Repo do end ############# + article_sink_mutation(:repo) article_pin_mutation(:repo) article_mark_delete_mutation(:repo) article_delete_mutation(:repo) diff --git a/lib/helper/certification.ex b/lib/helper/certification.ex index e341c41d7..8d0ea2481 100644 --- a/lib/helper/certification.ex +++ b/lib/helper/certification.ex @@ -58,12 +58,21 @@ defmodule Helper.Certification do "job.community.move", "job.community.unmirror", # flag on content + # pin/undo_pin "post.pin", "post.undo_pin", "job.pin", "job.undo_pin", "repo.pin", "repo.undo_pin", + # sink/undo_sink + "post.sink", + "post.undo_sink", + "job.sink", + "job.undo_sink", + "repo.sink", + "repo.undo_sink", + # "post.mark_delete", "post.undo_mark_delete", "job.mark_delete", diff --git a/lib/helper/error_code.ex b/lib/helper/error_code.ex index 47769939a..247fab5c7 100644 --- a/lib/helper/error_code.ex +++ b/lib/helper/error_code.ex @@ -48,6 +48,7 @@ defmodule Helper.ErrorCode do def ecode(:private_collect_folder), do: @article_base + 4 def ecode(:mirror_article), do: @article_base + 5 def ecode(:invalid_domain_tag), do: @article_base + 6 + def ecode(:undo_sink_old_article), do: @article_base + 7 def ecode, do: @default_base # def ecode(_), do: @default_base diff --git a/lib/helper/query_builder.ex b/lib/helper/query_builder.ex index 7c1f921be..1ddf852e4 100644 --- a/lib/helper/query_builder.ex +++ b/lib/helper/query_builder.ex @@ -102,10 +102,16 @@ defmodule Helper.QueryBuilder do def filter_pack(queryable, filter) when is_map(filter) do Enum.reduce(filter, queryable, fn + {:sort, :desc_active}, queryable -> + queryable |> order_by(desc: :active_at) + {:sort, :desc_inserted}, queryable -> # queryable |> order_by(^sort_strategy(:desc_inserted)) queryable |> order_by(desc: :inserted_at) + {:sort, :desc_active}, queryable -> + queryable |> order_by(desc: :active_at) + {:sort, :asc_inserted}, queryable -> queryable |> order_by(asc: :inserted_at) diff --git a/priv/repo/migrations/20210531072723_add_active_at_to_articles.exs b/priv/repo/migrations/20210531072723_add_active_at_to_articles.exs new file mode 100644 index 000000000..c4da91986 --- /dev/null +++ b/priv/repo/migrations/20210531072723_add_active_at_to_articles.exs @@ -0,0 +1,11 @@ +defmodule GroupherServer.Repo.Migrations.AddActiveAtToArticles do + use Ecto.Migration + + # see https://elixirforum.com/t/ecto-datetime-and-utc-naive-datetime-in-migration/21213 + + def change do + alter(table(:cms_posts), do: add(:active_at, :utc_datetime)) + alter(table(:cms_jobs), do: add(:active_at, :utc_datetime)) + alter(table(:cms_repos), do: add(:active_at, :utc_datetime)) + end +end diff --git a/test/groupher_server/cms/article_tags/job_tag_test.exs b/test/groupher_server/cms/article_tags/job_tag_test.exs index 8018bb9b2..fe76502c4 100644 --- a/test/groupher_server/cms/article_tags/job_tag_test.exs +++ b/test/groupher_server/cms/article_tags/job_tag_test.exs @@ -43,7 +43,6 @@ defmodule GroupherServer.Test.CMS.ArticleTag.JobTag do ) end - @tag :wip test "tag can be deleted", ~m(community article_tag_attrs user)a do {:ok, article_tag} = CMS.create_article_tag(community, :job, article_tag_attrs, user) {:ok, article_tag} = ORM.find(ArticleTag, article_tag.id) diff --git a/test/groupher_server/cms/article_tags/post_tag_test.exs b/test/groupher_server/cms/article_tags/post_tag_test.exs index 8cf202b06..ee9ec6601 100644 --- a/test/groupher_server/cms/article_tags/post_tag_test.exs +++ b/test/groupher_server/cms/article_tags/post_tag_test.exs @@ -43,7 +43,6 @@ defmodule GroupherServer.Test.CMS.ArticleTag.PostTag do ) end - @tag :wip test "tag can be deleted", ~m(community article_tag_attrs user)a do {:ok, article_tag} = CMS.create_article_tag(community, :post, article_tag_attrs, user) {:ok, article_tag} = ORM.find(ArticleTag, article_tag.id) diff --git a/test/groupher_server/cms/article_tags/repo_tag_test.exs b/test/groupher_server/cms/article_tags/repo_tag_test.exs index 67ea981f2..8021c958e 100644 --- a/test/groupher_server/cms/article_tags/repo_tag_test.exs +++ b/test/groupher_server/cms/article_tags/repo_tag_test.exs @@ -43,7 +43,6 @@ defmodule GroupherServer.Test.CMS.ArticleTag.RepoTag do ) end - @tag :wip test "tag can be deleted", ~m(community article_tag_attrs user)a do {:ok, article_tag} = CMS.create_article_tag(community, :repo, article_tag_attrs, user) {:ok, article_tag} = ORM.find(ArticleTag, article_tag.id) diff --git a/test/groupher_server/cms/job_test.exs b/test/groupher_server/cms/articles/job_test.exs similarity index 58% rename from test/groupher_server/cms/job_test.exs rename to test/groupher_server/cms/articles/job_test.exs index f08b76da5..c52324a02 100644 --- a/test/groupher_server/cms/job_test.exs +++ b/test/groupher_server/cms/articles/job_test.exs @@ -1,9 +1,11 @@ -defmodule GroupherServer.Test.Job do +defmodule GroupherServer.Test.Articles.Job do use GroupherServer.TestTools alias GroupherServer.CMS alias Helper.ORM + @last_year Timex.shift(Timex.beginning_of_year(Timex.now()), days: -3, seconds: -1) + setup do {:ok, user} = db_insert(:user) {:ok, user2} = db_insert(:user) @@ -25,6 +27,13 @@ defmodule GroupherServer.Test.Job do assert found.title == job.title end + test "created job should have a acitve_at field, same with inserted_at", + ~m(user community job_attrs)a do + {:ok, job} = CMS.create_article(community, :job, job_attrs, user) + + assert job.active_at == job.inserted_at + end + test "read job should update views and meta viewed_user_list", ~m(job_attrs community user user2)a do {:ok, job} = CMS.create_article(community, :job, job_attrs, user) @@ -84,4 +93,51 @@ defmodule GroupherServer.Test.Job do assert {:error, _} = CMS.create_article(ivalid_community, :job, invalid_attrs, user) end end + + describe "[cms job sink/undo_sink]" do + @tag :wip2 + test "if a job is too old, read job should update can_undo_sink flag", + ~m(user community job_attrs)a do + {:ok, job} = CMS.create_article(community, :job, job_attrs, user) + + assert job.meta.can_undo_sink + + {:ok, job_last_year} = db_insert(:job, %{title: "last year", inserted_at: @last_year}) + {:ok, job_last_year} = CMS.read_article(:job, job_last_year.id) + assert not job_last_year.meta.can_undo_sink + + {:ok, job_last_year} = CMS.read_article(:job, job_last_year.id, user) + assert not job_last_year.meta.can_undo_sink + end + + @tag :wip2 + test "can sink a job", ~m(user community job_attrs)a do + {:ok, job} = CMS.create_article(community, :job, job_attrs, user) + assert not job.meta.is_sinked + + {:ok, job} = CMS.sink_article(:job, job.id) + assert job.meta.is_sinked + assert job.active_at == job.inserted_at + end + + @tag :wip2 + test "can undo sink job", ~m(user community job_attrs)a do + {:ok, job} = CMS.create_article(community, :job, job_attrs, user) + {:ok, job} = CMS.sink_article(:job, job.id) + assert job.meta.is_sinked + assert job.meta.last_active_at == job.active_at + + {:ok, job} = CMS.undo_sink_article(:job, job.id) + assert not job.meta.is_sinked + assert job.active_at == job.meta.last_active_at + end + + @tag :wip2 + test "can not undo sink to old job", ~m()a do + {:ok, job_last_year} = db_insert(:job, %{title: "last year", inserted_at: @last_year}) + + {:error, reason} = CMS.undo_sink_article(:job, job_last_year.id) + is_error?(reason, :undo_sink_old_article) + end + end end diff --git a/test/groupher_server/cms/post_meta_test.exs b/test/groupher_server/cms/articles/post_meta_test.exs similarity index 92% rename from test/groupher_server/cms/post_meta_test.exs rename to test/groupher_server/cms/articles/post_meta_test.exs index 8db27ed26..7974cfcf2 100644 --- a/test/groupher_server/cms/post_meta_test.exs +++ b/test/groupher_server/cms/articles/post_meta_test.exs @@ -42,11 +42,12 @@ defmodule GroupherServer.Test.CMS.PostMeta do assert post.meta.is_edited end - test "post 's lock article should work", ~m(user community post_attrs)a do + @tag :wip + test "post's lock article should work", ~m(user community post_attrs)a do {:ok, post} = CMS.create_article(community, :post, post_attrs, user) assert not post.meta.is_comment_locked - {:ok, _} = CMS.lock_article_comment(post) + {:ok, _} = CMS.lock_article_comment(:post, post.id) {:ok, post} = ORM.find_by(Post, id: post.id) assert post.meta.is_comment_locked diff --git a/test/groupher_server/cms/post_test.exs b/test/groupher_server/cms/articles/post_test.exs similarity index 60% rename from test/groupher_server/cms/post_test.exs rename to test/groupher_server/cms/articles/post_test.exs index 3b00afbc5..ff1c41d27 100644 --- a/test/groupher_server/cms/post_test.exs +++ b/test/groupher_server/cms/articles/post_test.exs @@ -1,9 +1,13 @@ -defmodule GroupherServer.Test.CMS.Post do +defmodule GroupherServer.Test.CMS.Articles.Post do use GroupherServer.TestTools alias Helper.ORM alias GroupherServer.CMS + alias CMS.{Author, Community} + + @last_year Timex.shift(Timex.beginning_of_year(Timex.now()), days: -3, seconds: -1) + setup do {:ok, user} = db_insert(:user) {:ok, user2} = db_insert(:user) @@ -16,8 +20,6 @@ defmodule GroupherServer.Test.CMS.Post do end describe "[cms post curd]" do - alias CMS.{Author, Community} - test "can create post with valid attrs", ~m(user community post_attrs)a do assert {:error, _} = ORM.find_by(Author, user_id: user.id) @@ -26,6 +28,13 @@ defmodule GroupherServer.Test.CMS.Post do assert post.title == post_attrs.title end + test "created post should have a acitve_at field, same with inserted_at", + ~m(user community post_attrs)a do + {:ok, post} = CMS.create_article(community, :post, post_attrs, user) + + assert post.active_at == post.inserted_at + end + test "read post should update views and meta viewed_user_list", ~m(post_attrs community user user2)a do {:ok, post} = CMS.create_article(community, :post, post_attrs, user) @@ -94,4 +103,51 @@ defmodule GroupherServer.Test.CMS.Post do assert {:error, _} = CMS.create_article(ivalid_community, :post, invalid_attrs, user) end end + + describe "[cms post sink/undo_sink]" do + @tag :wip2 + test "if a post is too old, read post should update can_undo_sink flag", + ~m(user community post_attrs)a do + {:ok, post} = CMS.create_article(community, :post, post_attrs, user) + + assert post.meta.can_undo_sink + + {:ok, post_last_year} = db_insert(:post, %{title: "last year", inserted_at: @last_year}) + {:ok, post_last_year} = CMS.read_article(:post, post_last_year.id) + assert not post_last_year.meta.can_undo_sink + + {:ok, post_last_year} = CMS.read_article(:post, post_last_year.id, user) + assert not post_last_year.meta.can_undo_sink + end + + @tag :wip2 + test "can sink a post", ~m(user community post_attrs)a do + {:ok, post} = CMS.create_article(community, :post, post_attrs, user) + assert not post.meta.is_sinked + + {:ok, post} = CMS.sink_article(:post, post.id) + assert post.meta.is_sinked + assert post.active_at == post.inserted_at + end + + @tag :wip2 + test "can undo sink post", ~m(user community post_attrs)a do + {:ok, post} = CMS.create_article(community, :post, post_attrs, user) + {:ok, post} = CMS.sink_article(:post, post.id) + assert post.meta.is_sinked + assert post.meta.last_active_at == post.active_at + + {:ok, post} = CMS.undo_sink_article(:post, post.id) + assert not post.meta.is_sinked + assert post.active_at == post.meta.last_active_at + end + + @tag :wip2 + test "can not undo sink to old post", ~m()a do + {:ok, post_last_year} = db_insert(:post, %{title: "last year", inserted_at: @last_year}) + + {:error, reason} = CMS.undo_sink_article(:post, post_last_year.id) + is_error?(reason, :undo_sink_old_article) + end + end end diff --git a/test/groupher_server/cms/repo_test.exs b/test/groupher_server/cms/articles/repo_test.exs similarity index 61% rename from test/groupher_server/cms/repo_test.exs rename to test/groupher_server/cms/articles/repo_test.exs index 24c981b46..7059778e5 100644 --- a/test/groupher_server/cms/repo_test.exs +++ b/test/groupher_server/cms/articles/repo_test.exs @@ -1,9 +1,11 @@ -defmodule GroupherServer.Test.Repo do +defmodule GroupherServer.Test.Articles.Repo do use GroupherServer.TestTools alias Helper.ORM alias GroupherServer.CMS + @last_year Timex.shift(Timex.beginning_of_year(Timex.now()), days: -3, seconds: -1) + setup do {:ok, user} = db_insert(:user) {:ok, user2} = db_insert(:user) @@ -27,6 +29,13 @@ defmodule GroupherServer.Test.Repo do assert repo.contributors |> length !== 0 end + test "created repo should have a acitve_at field, same with inserted_at", + ~m(user community repo_attrs)a do + {:ok, repo} = CMS.create_article(community, :repo, repo_attrs, user) + + assert repo.active_at == repo.inserted_at + end + test "read repo should update views and meta viewed_user_list", ~m(repo_attrs community user user2)a do {:ok, repo} = CMS.create_article(community, :repo, repo_attrs, user) @@ -95,4 +104,51 @@ defmodule GroupherServer.Test.Repo do assert {:error, _} = CMS.create_article(ivalid_community, :repo, invalid_attrs, user) end end + + describe "[cms repo sink/undo_sink]" do + @tag :wip2 + test "if a repo is too old, read repo should update can_undo_sink flag", + ~m(user community repo_attrs)a do + {:ok, repo} = CMS.create_article(community, :repo, repo_attrs, user) + + assert repo.meta.can_undo_sink + + {:ok, repo_last_year} = db_insert(:repo, %{title: "last year", inserted_at: @last_year}) + {:ok, repo_last_year} = CMS.read_article(:repo, repo_last_year.id) + assert not repo_last_year.meta.can_undo_sink + + {:ok, repo_last_year} = CMS.read_article(:repo, repo_last_year.id, user) + assert not repo_last_year.meta.can_undo_sink + end + + @tag :wip2 + test "can sink a repo", ~m(user community repo_attrs)a do + {:ok, repo} = CMS.create_article(community, :repo, repo_attrs, user) + assert not repo.meta.is_sinked + + {:ok, repo} = CMS.sink_article(:repo, repo.id) + assert repo.meta.is_sinked + assert repo.active_at == repo.inserted_at + end + + @tag :wip2 + test "can undo sink repo", ~m(user community repo_attrs)a do + {:ok, repo} = CMS.create_article(community, :repo, repo_attrs, user) + {:ok, repo} = CMS.sink_article(:repo, repo.id) + assert repo.meta.is_sinked + assert repo.meta.last_active_at == repo.active_at + + {:ok, repo} = CMS.undo_sink_article(:repo, repo.id) + assert not repo.meta.is_sinked + assert repo.active_at == repo.meta.last_active_at + end + + @tag :wip2 + test "can not undo sink to old repo", ~m()a do + {:ok, repo_last_year} = db_insert(:repo, %{title: "last year", inserted_at: @last_year}) + + {:error, reason} = CMS.undo_sink_article(:repo, repo_last_year.id) + is_error?(reason, :undo_sink_old_article) + end + end end diff --git a/test/groupher_server/cms/comments/job_comment_test.exs b/test/groupher_server/cms/comments/job_comment_test.exs index 6f7c15e2f..4aa668d44 100644 --- a/test/groupher_server/cms/comments/job_comment_test.exs +++ b/test/groupher_server/cms/comments/job_comment_test.exs @@ -2,12 +2,15 @@ defmodule GroupherServer.Test.CMS.Comments.JobComment do @moduledoc false use GroupherServer.TestTools + import Helper.Utils, only: [get_config: 2] alias Helper.ORM alias GroupherServer.{Accounts, CMS} alias CMS.{ArticleComment, ArticlePinnedComment, Embeds, Job} + @active_period get_config(:article, :active_period_days) + @delete_hint CMS.ArticleComment.delete_hint() @report_threshold_for_fold ArticleComment.report_threshold_for_fold() @default_comment_meta Embeds.ArticleCommentMeta.default_meta() @@ -17,8 +20,9 @@ defmodule GroupherServer.Test.CMS.Comments.JobComment do {:ok, user} = db_insert(:user) {:ok, user2} = db_insert(:user) {:ok, job} = db_insert(:job) + {:ok, community} = db_insert(:community) - {:ok, ~m(user user2 job)a} + {:ok, ~m(community user user2 job)a} end describe "[basic article comment]" do @@ -37,6 +41,53 @@ defmodule GroupherServer.Test.CMS.Comments.JobComment do assert comment.meta |> Map.from_struct() |> Map.delete(:id) == @default_comment_meta end + test "create comment should update active timestamp of job", ~m(user job)a do + Process.sleep(1000) + {:ok, _comment} = CMS.create_article_comment(:job, job.id, "job comment", user) + {:ok, job} = ORM.find(Job, job.id, preload: :article_comments) + + assert not is_nil(job.active_at) + assert job.active_at > job.inserted_at + end + + test "job author create comment will not update active timestamp", ~m(community user)a do + job_attrs = mock_attrs(:job, %{community_id: community.id}) + {:ok, job} = CMS.create_article(community, :job, job_attrs, user) + {:ok, job} = ORM.find(Job, job.id, preload: [author: :user]) + + Process.sleep(1000) + + {:ok, _comment} = CMS.create_article_comment(:job, job.id, "job comment", job.author.user) + + {:ok, job} = ORM.find(Job, job.id, preload: :article_comments) + + assert not is_nil(job.active_at) + assert job.active_at == job.inserted_at + end + + test "old job will not update active after comment created", ~m(user)a do + active_period_days = Map.get(@active_period, :job) + + inserted_at = + Timex.shift(Timex.now(), days: -(active_period_days - 1)) |> Timex.to_datetime() + + {:ok, job} = db_insert(:job, %{inserted_at: inserted_at}) + {:ok, _comment} = CMS.create_article_comment(:job, job.id, "job comment", user) + {:ok, job} = ORM.find(Job, job.id) + + assert job.active_at |> DateTime.to_date() == DateTime.utc_now() |> DateTime.to_date() + + # ---- + inserted_at = + Timex.shift(Timex.now(), days: -(active_period_days + 1)) |> Timex.to_datetime() + + {:ok, job} = db_insert(:job, %{inserted_at: inserted_at}) + {:ok, _comment} = CMS.create_article_comment(:job, job.id, "job comment", user) + {:ok, job} = ORM.find(Job, job.id) + + assert job.active_at |> DateTime.to_unix() !== DateTime.utc_now() |> DateTime.to_unix() + end + test "comment can be updated", ~m(job user)a do {:ok, comment} = CMS.create_article_comment(:job, job.id, "job comment", user) @@ -271,8 +322,7 @@ defmodule GroupherServer.Test.CMS.Comments.JobComment do # {:ok, comment} = ORM.find(ArticleComment, comment.id) # end - test "can undo a report with other user report it too", - ~m(user user2 job)a do + test "can undo a report with other user report it too", ~m(user user2 job)a do {:ok, comment} = CMS.create_article_comment(:job, job.id, "commment", user) {:ok, _comment} = CMS.report_article_comment(comment.id, "reason", "attr", user) @@ -291,6 +341,7 @@ defmodule GroupherServer.Test.CMS.Comments.JobComment do filter = %{content_type: :article_comment, content_id: comment.id, page: 1, size: 20} {:ok, all_reports} = CMS.paged_reports(filter) + assert all_reports.total_count == 1 report = all_reports.entries |> List.first() @@ -363,7 +414,12 @@ defmodule GroupherServer.Test.CMS.Comments.JobComment do end) {:ok, paged_comments} = - CMS.paged_article_comments(:job, job.id, %{page: page_number, size: page_size}, :replies) + CMS.paged_article_comments( + :job, + job.id, + %{page: page_number, size: page_size}, + :replies + ) random_comment = all_comments |> Enum.at(Enum.random(0..total_count)) @@ -393,7 +449,12 @@ defmodule GroupherServer.Test.CMS.Comments.JobComment do {:ok, pined_comment_2} = CMS.pin_article_comment(random_comment_2.id) {:ok, paged_comments} = - CMS.paged_article_comments(:job, job.id, %{page: page_number, size: page_size}, :replies) + CMS.paged_article_comments( + :job, + job.id, + %{page: page_number, size: page_size}, + :replies + ) assert pined_comment_1.id == List.first(paged_comments.entries) |> Map.get(:id) assert pined_comment_2.id == Enum.at(paged_comments.entries, 1) |> Map.get(:id) @@ -420,7 +481,12 @@ defmodule GroupherServer.Test.CMS.Comments.JobComment do {:ok, pined_comment_2} = CMS.pin_article_comment(random_comment_2.id) {:ok, paged_comments} = - CMS.paged_article_comments(:job, job.id, %{page: page_number, size: page_size}, :replies) + CMS.paged_article_comments( + :job, + job.id, + %{page: page_number, size: page_size}, + :replies + ) assert not exist_in?(pined_comment_1, paged_comments.entries) assert not exist_in?(pined_comment_2, paged_comments.entries) @@ -450,7 +516,12 @@ defmodule GroupherServer.Test.CMS.Comments.JobComment do {:ok, _comment} = CMS.fold_article_comment(random_comment_3.id, user) {:ok, paged_comments} = - CMS.paged_article_comments(:job, job.id, %{page: page_number, size: page_size}, :replies) + CMS.paged_article_comments( + :job, + job.id, + %{page: page_number, size: page_size}, + :replies + ) assert not exist_in?(random_comment_1, paged_comments.entries) assert not exist_in?(random_comment_2, paged_comments.entries) @@ -509,7 +580,12 @@ defmodule GroupherServer.Test.CMS.Comments.JobComment do {:ok, deleted_comment} = CMS.delete_article_comment(random_comment) {:ok, paged_comments} = - CMS.paged_article_comments(:job, job.id, %{page: page_number, size: page_size}, :replies) + CMS.paged_article_comments( + :job, + job.id, + %{page: page_number, size: page_size}, + :replies + ) assert exist_in?(deleted_comment, paged_comments.entries) assert deleted_comment.is_deleted diff --git a/test/groupher_server/cms/comments/post_comment_test.exs b/test/groupher_server/cms/comments/post_comment_test.exs index 69210d99a..066009ba8 100644 --- a/test/groupher_server/cms/comments/post_comment_test.exs +++ b/test/groupher_server/cms/comments/post_comment_test.exs @@ -2,12 +2,15 @@ defmodule GroupherServer.Test.CMS.Comments.PostComment do @moduledoc false use GroupherServer.TestTools + import Helper.Utils, only: [get_config: 2] alias Helper.ORM alias GroupherServer.{Accounts, CMS} alias CMS.{ArticleComment, ArticlePinnedComment, Embeds, Post} + @active_period get_config(:article, :active_period_days) + @delete_hint CMS.ArticleComment.delete_hint() @report_threshold_for_fold ArticleComment.report_threshold_for_fold() @default_comment_meta Embeds.ArticleCommentMeta.default_meta() @@ -17,8 +20,9 @@ defmodule GroupherServer.Test.CMS.Comments.PostComment do {:ok, user} = db_insert(:user) {:ok, user2} = db_insert(:user) {:ok, post} = db_insert(:post) + {:ok, community} = db_insert(:community) - {:ok, ~m(user user2 post)a} + {:ok, ~m(community user user2 post)a} end describe "[basic article comment]" do @@ -37,6 +41,54 @@ defmodule GroupherServer.Test.CMS.Comments.PostComment do assert comment.meta |> Map.from_struct() |> Map.delete(:id) == @default_comment_meta end + test "create comment should update active timestamp of post", ~m(user post)a do + Process.sleep(1000) + {:ok, _comment} = CMS.create_article_comment(:post, post.id, "post comment", user) + {:ok, post} = ORM.find(Post, post.id, preload: :article_comments) + + assert not is_nil(post.active_at) + assert post.active_at > post.inserted_at + end + + test "post author create comment will not update active timestamp", ~m(community user)a do + post_attrs = mock_attrs(:post, %{community_id: community.id}) + {:ok, post} = CMS.create_article(community, :post, post_attrs, user) + {:ok, post} = ORM.find(Post, post.id, preload: [author: :user]) + + Process.sleep(1000) + + {:ok, _comment} = + CMS.create_article_comment(:post, post.id, "post comment", post.author.user) + + {:ok, post} = ORM.find(Post, post.id, preload: :article_comments) + + assert not is_nil(post.active_at) + assert post.active_at == post.inserted_at + end + + test "old post will not update active after comment created", ~m(user)a do + active_period_days = Map.get(@active_period, :post) + + inserted_at = + Timex.shift(Timex.now(), days: -(active_period_days - 1)) |> Timex.to_datetime() + + {:ok, post} = db_insert(:post, %{inserted_at: inserted_at}) + {:ok, _comment} = CMS.create_article_comment(:post, post.id, "post comment", user) + {:ok, post} = ORM.find(Post, post.id) + + assert post.active_at |> DateTime.to_date() == DateTime.utc_now() |> DateTime.to_date() + + # ---- + inserted_at = + Timex.shift(Timex.now(), days: -(active_period_days + 1)) |> Timex.to_datetime() + + {:ok, post} = db_insert(:post, %{inserted_at: inserted_at}) + {:ok, _comment} = CMS.create_article_comment(:post, post.id, "post comment", user) + {:ok, post} = ORM.find(Post, post.id) + + assert post.active_at |> DateTime.to_unix() !== DateTime.utc_now() |> DateTime.to_unix() + end + test "comment can be updated", ~m(post user)a do {:ok, comment} = CMS.create_article_comment(:post, post.id, "post comment", user) diff --git a/test/groupher_server/cms/comments/repo_comment_test.exs b/test/groupher_server/cms/comments/repo_comment_test.exs index 64cfc2e4a..f43f9d2a8 100644 --- a/test/groupher_server/cms/comments/repo_comment_test.exs +++ b/test/groupher_server/cms/comments/repo_comment_test.exs @@ -2,12 +2,15 @@ defmodule GroupherServer.Test.CMS.Comments.RepoComment do @moduledoc false use GroupherServer.TestTools + import Helper.Utils, only: [get_config: 2] alias Helper.ORM alias GroupherServer.{Accounts, CMS} alias CMS.{ArticleComment, ArticlePinnedComment, Embeds, Repo} + @active_period get_config(:article, :active_period_days) + @delete_hint CMS.ArticleComment.delete_hint() @report_threshold_for_fold ArticleComment.report_threshold_for_fold() @default_comment_meta Embeds.ArticleCommentMeta.default_meta() @@ -17,8 +20,9 @@ defmodule GroupherServer.Test.CMS.Comments.RepoComment do {:ok, user} = db_insert(:user) {:ok, user2} = db_insert(:user) {:ok, repo} = db_insert(:repo) + {:ok, community} = db_insert(:community) - {:ok, ~m(user user2 repo)a} + {:ok, ~m(community user user2 repo)a} end describe "[basic article comment]" do @@ -37,6 +41,54 @@ defmodule GroupherServer.Test.CMS.Comments.RepoComment do assert comment.meta |> Map.from_struct() |> Map.delete(:id) == @default_comment_meta end + test "create comment should update active timestamp of repo", ~m(user repo)a do + Process.sleep(1000) + {:ok, _comment} = CMS.create_article_comment(:repo, repo.id, "repo comment", user) + {:ok, repo} = ORM.find(Repo, repo.id, preload: :article_comments) + + assert not is_nil(repo.active_at) + assert repo.active_at > repo.inserted_at + end + + test "repo author create comment will not update active timestamp", ~m(community user)a do + repo_attrs = mock_attrs(:repo, %{community_id: community.id}) + {:ok, repo} = CMS.create_article(community, :repo, repo_attrs, user) + {:ok, repo} = ORM.find(Repo, repo.id, preload: [author: :user]) + + Process.sleep(1000) + + {:ok, _comment} = + CMS.create_article_comment(:repo, repo.id, "repo comment", repo.author.user) + + {:ok, repo} = ORM.find(Repo, repo.id, preload: :article_comments) + + assert not is_nil(repo.active_at) + assert repo.active_at == repo.inserted_at + end + + test "old repo will not update active after comment created", ~m(user)a do + active_period_days = Map.get(@active_period, :repo) + + inserted_at = + Timex.shift(Timex.now(), days: -(active_period_days - 1)) |> Timex.to_datetime() + + {:ok, repo} = db_insert(:repo, %{inserted_at: inserted_at}) + {:ok, _comment} = CMS.create_article_comment(:repo, repo.id, "repo comment", user) + {:ok, repo} = ORM.find(Repo, repo.id) + + assert repo.active_at |> DateTime.to_date() == DateTime.utc_now() |> DateTime.to_date() + + # ---- + inserted_at = + Timex.shift(Timex.now(), days: -(active_period_days + 1)) |> Timex.to_datetime() + + {:ok, repo} = db_insert(:repo, %{inserted_at: inserted_at}) + {:ok, _comment} = CMS.create_article_comment(:repo, repo.id, "repo comment", user) + {:ok, repo} = ORM.find(Repo, repo.id) + + assert repo.active_at |> DateTime.to_unix() !== DateTime.utc_now() |> DateTime.to_unix() + end + test "comment can be updated", ~m(repo user)a do {:ok, comment} = CMS.create_article_comment(:repo, repo.id, "repo comment", user) @@ -271,8 +323,7 @@ defmodule GroupherServer.Test.CMS.Comments.RepoComment do # {:ok, comment} = ORM.find(ArticleComment, comment.id) # end - test "can undo a report with other user report it too", - ~m(user user2 repo)a do + test "can undo a report with other user report it too", ~m(user user2 repo)a do {:ok, comment} = CMS.create_article_comment(:repo, repo.id, "commment", user) {:ok, _comment} = CMS.report_article_comment(comment.id, "reason", "attr", user) @@ -291,6 +342,7 @@ defmodule GroupherServer.Test.CMS.Comments.RepoComment do filter = %{content_type: :article_comment, content_id: comment.id, page: 1, size: 20} {:ok, all_reports} = CMS.paged_reports(filter) + assert all_reports.total_count == 1 report = all_reports.entries |> List.first() diff --git a/test/groupher_server/cms/community/community_meta_test.exs b/test/groupher_server/cms/community/community_meta_test.exs index 0c8bbd7f2..787ba73b6 100644 --- a/test/groupher_server/cms/community/community_meta_test.exs +++ b/test/groupher_server/cms/community/community_meta_test.exs @@ -24,13 +24,11 @@ defmodule GroupherServer.Test.CMS.Community.CommunityMeta do end describe "[article count meta]" do - @tag :wip test "created community should have default meta ", ~m(community_attrs)a do {:ok, community} = CMS.create_community(community_attrs) assert community.meta |> strip_struct == @default_meta end - @tag :wip test "update legacy community should add default meta", ~m(community)a do assert is_nil(community.meta) @@ -38,7 +36,6 @@ defmodule GroupherServer.Test.CMS.Community.CommunityMeta do assert community.meta |> strip_struct == @default_meta end - @tag :wip3 test "create a post should inc posts_count in meta", ~m(user community community2 community3)a do post_attrs = mock_attrs(:post) @@ -59,7 +56,6 @@ defmodule GroupherServer.Test.CMS.Community.CommunityMeta do assert community2.meta.posts_count == 1 end - @tag :wip3 test "create a job should inc jobs_count in meta", ~m(user community community2 community3)a do job_attrs = mock_attrs(:job) @@ -80,7 +76,6 @@ defmodule GroupherServer.Test.CMS.Community.CommunityMeta do assert community2.meta.jobs_count == 1 end - @tag :wip3 test "create a repo should inc repos_count in meta", ~m(user community community2 community3)a do repo_attrs = mock_attrs(:repo) @@ -101,7 +96,6 @@ defmodule GroupherServer.Test.CMS.Community.CommunityMeta do assert community2.meta.repos_count == 1 end - @tag :wip3 test "create a multi article should inc repos_count in meta", ~m(user community community2)a do post_attrs = mock_attrs(:post) diff --git a/test/groupher_server_web/mutation/cms/flags/job_flag_test.exs b/test/groupher_server_web/mutation/cms/flags/job_flag_test.exs index e4bfed07e..2e18d1fc6 100644 --- a/test/groupher_server_web/mutation/cms/flags/job_flag_test.exs +++ b/test/groupher_server_web/mutation/cms/flags/job_flag_test.exs @@ -38,7 +38,6 @@ defmodule GroupherServer.Test.Mutation.Flags.JobFlag do assert updated["markDelete"] == true end - @tag :wip3 test "mark delete job should update job's communities meta count", ~m(user)a do community_attrs = mock_attrs(:community) |> Map.merge(%{user_id: user.id}) {:ok, community} = CMS.create_community(community_attrs) @@ -88,7 +87,6 @@ defmodule GroupherServer.Test.Mutation.Flags.JobFlag do assert updated["markDelete"] == false end - @tag :wip3 test "undo mark delete job should update job's communities meta count", ~m(user)a do community_attrs = mock_attrs(:community) |> Map.merge(%{user_id: user.id}) {:ok, community} = CMS.create_community(community_attrs) diff --git a/test/groupher_server_web/mutation/cms/flags/post_flag_test.exs b/test/groupher_server_web/mutation/cms/flags/post_flag_test.exs index f80bcd666..b4069e007 100644 --- a/test/groupher_server_web/mutation/cms/flags/post_flag_test.exs +++ b/test/groupher_server_web/mutation/cms/flags/post_flag_test.exs @@ -38,7 +38,6 @@ defmodule GroupherServer.Test.Mutation.Flags.PostFlag do assert updated["markDelete"] == true end - @tag :wip3 test "mark delete post should update post's communities meta count", ~m(user)a do community_attrs = mock_attrs(:community) |> Map.merge(%{user_id: user.id}) {:ok, community} = CMS.create_community(community_attrs) @@ -88,7 +87,6 @@ defmodule GroupherServer.Test.Mutation.Flags.PostFlag do assert updated["markDelete"] == false end - @tag :wip3 test "undo mark delete post should update post's communities meta count", ~m(user)a do community_attrs = mock_attrs(:community) |> Map.merge(%{user_id: user.id}) {:ok, community} = CMS.create_community(community_attrs) diff --git a/test/groupher_server_web/mutation/cms/flags/repo_flag_test.exs b/test/groupher_server_web/mutation/cms/flags/repo_flag_test.exs index 995b94cc3..78963fd5f 100644 --- a/test/groupher_server_web/mutation/cms/flags/repo_flag_test.exs +++ b/test/groupher_server_web/mutation/cms/flags/repo_flag_test.exs @@ -38,7 +38,6 @@ defmodule GroupherServer.Test.Mutation.Flags.RepoFlag do assert updated["markDelete"] == true end - @tag :wip3 test "mark delete repo should update repo's communities meta count", ~m(user)a do community_attrs = mock_attrs(:community) |> Map.merge(%{user_id: user.id}) {:ok, community} = CMS.create_community(community_attrs) @@ -88,7 +87,6 @@ defmodule GroupherServer.Test.Mutation.Flags.RepoFlag do assert updated["markDelete"] == false end - @tag :wip3 test "undo mark delete repo should update repo's communities meta count", ~m(user)a do community_attrs = mock_attrs(:community) |> Map.merge(%{user_id: user.id}) {:ok, community} = CMS.create_community(community_attrs) diff --git a/test/groupher_server_web/mutation/cms/sink/job_sink_test.exs b/test/groupher_server_web/mutation/cms/sink/job_sink_test.exs new file mode 100644 index 000000000..9b7863716 --- /dev/null +++ b/test/groupher_server_web/mutation/cms/sink/job_sink_test.exs @@ -0,0 +1,80 @@ +defmodule GroupherServer.Test.Mutation.Sink.JobSink do + @moduledoc false + use GroupherServer.TestTools + + alias GroupherServer.CMS + alias CMS.Job + + alias Helper.ORM + + setup do + {:ok, user} = db_insert(:user) + {:ok, community} = db_insert(:community) + {:ok, job} = CMS.create_article(community, :job, mock_attrs(:job), user) + + guest_conn = simu_conn(:guest) + user_conn = simu_conn(:user, user) + + {:ok, ~m(user_conn guest_conn community job user)a} + end + + describe "[job sink]" do + @query """ + mutation($id: ID!, $communityId: ID!){ + sinkJob(id: $id, communityId: $communityId) { + id + } + } + """ + @tag :wip + test "login user can sink a job", ~m(user_conn community job)a do + variables = %{id: job.id, communityId: community.id} + passport_rules = %{community.raw => %{"job.sink" => true}} + rule_conn = simu_conn(:user, cms: passport_rules) + + result = rule_conn |> mutation_result(@query, variables, "sinkJob") + assert result["id"] == to_string(job.id) + + {:ok, job} = ORM.find(Job, job.id) + assert job.meta.is_sinked + assert job.active_at == job.inserted_at + end + + @tag :wip + test "unauth user sink a job fails", ~m(guest_conn community job)a do + variables = %{id: job.id, communityId: community.id} + + assert guest_conn |> mutation_get_error?(@query, variables, ecode(:account_login)) + end + + @query """ + mutation($id: ID!, $communityId: ID!){ + undoSinkJob(id: $id, communityId: $communityId) { + id + } + } + """ + @tag :wip + test "login user can undo sink to a job", ~m(community job)a do + variables = %{id: job.id, communityId: community.id} + + passport_rules = %{community.raw => %{"job.undo_sink" => true}} + rule_conn = simu_conn(:user, cms: passport_rules) + + {:ok, _} = CMS.sink_article(:job, job.id) + updated = rule_conn |> mutation_result(@query, variables, "undoSinkJob") + assert updated["id"] == to_string(job.id) + + {:ok, job} = ORM.find(Job, job.id) + assert not job.meta.is_sinked + end + + :wip2 + + test "unauth user undo sink a job fails", ~m(guest_conn community job)a do + variables = %{id: job.id, communityId: community.id} + + assert guest_conn |> mutation_get_error?(@query, variables, ecode(:account_login)) + end + end +end diff --git a/test/groupher_server_web/mutation/cms/sink/post_sink_test.exs b/test/groupher_server_web/mutation/cms/sink/post_sink_test.exs new file mode 100644 index 000000000..407039508 --- /dev/null +++ b/test/groupher_server_web/mutation/cms/sink/post_sink_test.exs @@ -0,0 +1,80 @@ +defmodule GroupherServer.Test.Mutation.Sink.PostSink do + @moduledoc false + use GroupherServer.TestTools + + alias GroupherServer.CMS + alias CMS.Post + + alias Helper.ORM + + setup do + {:ok, user} = db_insert(:user) + {:ok, community} = db_insert(:community) + {:ok, post} = CMS.create_article(community, :post, mock_attrs(:post), user) + + guest_conn = simu_conn(:guest) + user_conn = simu_conn(:user, user) + + {:ok, ~m(user_conn guest_conn community post user)a} + end + + describe "[post sink]" do + @query """ + mutation($id: ID!, $communityId: ID!){ + sinkPost(id: $id, communityId: $communityId) { + id + } + } + """ + @tag :wip + test "login user can sink a post", ~m(user_conn community post)a do + variables = %{id: post.id, communityId: community.id} + passport_rules = %{community.raw => %{"post.sink" => true}} + rule_conn = simu_conn(:user, cms: passport_rules) + + result = rule_conn |> mutation_result(@query, variables, "sinkPost") + assert result["id"] == to_string(post.id) + + {:ok, post} = ORM.find(Post, post.id) + assert post.meta.is_sinked + assert post.active_at == post.inserted_at + end + + @tag :wip + test "unauth user sink a post fails", ~m(guest_conn community post)a do + variables = %{id: post.id, communityId: community.id} + + assert guest_conn |> mutation_get_error?(@query, variables, ecode(:account_login)) + end + + @query """ + mutation($id: ID!, $communityId: ID!){ + undoSinkPost(id: $id, communityId: $communityId) { + id + } + } + """ + @tag :wip + test "login user can undo sink to a post", ~m(community post)a do + variables = %{id: post.id, communityId: community.id} + + passport_rules = %{community.raw => %{"post.undo_sink" => true}} + rule_conn = simu_conn(:user, cms: passport_rules) + + {:ok, _} = CMS.sink_article(:post, post.id) + updated = rule_conn |> mutation_result(@query, variables, "undoSinkPost") + assert updated["id"] == to_string(post.id) + + {:ok, post} = ORM.find(Post, post.id) + assert not post.meta.is_sinked + end + + :wip2 + + test "unauth user undo sink a post fails", ~m(guest_conn community post)a do + variables = %{id: post.id, communityId: community.id} + + assert guest_conn |> mutation_get_error?(@query, variables, ecode(:account_login)) + end + end +end diff --git a/test/groupher_server_web/mutation/cms/sink/repo_sink_test.exs b/test/groupher_server_web/mutation/cms/sink/repo_sink_test.exs new file mode 100644 index 000000000..8de7d91de --- /dev/null +++ b/test/groupher_server_web/mutation/cms/sink/repo_sink_test.exs @@ -0,0 +1,80 @@ +defmodule GroupherServer.Test.Mutation.Sink.RepoSink do + @moduledoc false + use GroupherServer.TestTools + + alias GroupherServer.CMS + alias CMS.Repo + + alias Helper.ORM + + setup do + {:ok, user} = db_insert(:user) + {:ok, community} = db_insert(:community) + {:ok, repo} = CMS.create_article(community, :repo, mock_attrs(:repo), user) + + guest_conn = simu_conn(:guest) + user_conn = simu_conn(:user, user) + + {:ok, ~m(user_conn guest_conn community repo user)a} + end + + describe "[repo sink]" do + @query """ + mutation($id: ID!, $communityId: ID!){ + sinkRepo(id: $id, communityId: $communityId) { + id + } + } + """ + @tag :wip + test "login user can sink a repo", ~m(user_conn community repo)a do + variables = %{id: repo.id, communityId: community.id} + passport_rules = %{community.raw => %{"repo.sink" => true}} + rule_conn = simu_conn(:user, cms: passport_rules) + + result = rule_conn |> mutation_result(@query, variables, "sinkRepo") + assert result["id"] == to_string(repo.id) + + {:ok, repo} = ORM.find(Repo, repo.id) + assert repo.meta.is_sinked + assert repo.active_at == repo.inserted_at + end + + @tag :wip + test "unauth user sink a repo fails", ~m(guest_conn community repo)a do + variables = %{id: repo.id, communityId: community.id} + + assert guest_conn |> mutation_get_error?(@query, variables, ecode(:account_login)) + end + + @query """ + mutation($id: ID!, $communityId: ID!){ + undoSinkRepo(id: $id, communityId: $communityId) { + id + } + } + """ + @tag :wip + test "login user can undo sink to a repo", ~m(community repo)a do + variables = %{id: repo.id, communityId: community.id} + + passport_rules = %{community.raw => %{"repo.undo_sink" => true}} + rule_conn = simu_conn(:user, cms: passport_rules) + + {:ok, _} = CMS.sink_article(:repo, repo.id) + updated = rule_conn |> mutation_result(@query, variables, "undoSinkRepo") + assert updated["id"] == to_string(repo.id) + + {:ok, repo} = ORM.find(Repo, repo.id) + assert not repo.meta.is_sinked + end + + :wip2 + + test "unauth user undo sink a repo fails", ~m(guest_conn community repo)a do + variables = %{id: repo.id, communityId: community.id} + + assert guest_conn |> mutation_get_error?(@query, variables, ecode(:account_login)) + end + end +end diff --git a/test/groupher_server_web/query/cms/articles/job_test.exs b/test/groupher_server_web/query/cms/articles/job_test.exs index 6d66c221d..8dd09fbf9 100644 --- a/test/groupher_server_web/query/cms/articles/job_test.exs +++ b/test/groupher_server_web/query/cms/articles/job_test.exs @@ -19,7 +19,6 @@ defmodule GroupherServer.Test.Query.Articles.Job do } } """ - @tag :wip3 test "basic graphql query on job with logined user", ~m(user_conn job)a do variables = %{id: job.id} results = user_conn |> query_result(@query, variables, "job") diff --git a/test/groupher_server_web/query/cms/cms_test.exs b/test/groupher_server_web/query/cms/cms_test.exs index d36c8e431..dab25aec1 100644 --- a/test/groupher_server_web/query/cms/cms_test.exs +++ b/test/groupher_server_web/query/cms/cms_test.exs @@ -31,7 +31,6 @@ defmodule GroupherServer.Test.Query.CMS.Basic do } } """ - @tag :wip3 test "views should work", ~m(guest_conn)a do {:ok, community} = db_insert(:community) diff --git a/test/groupher_server_web/query/cms/community_meta_test.exs b/test/groupher_server_web/query/cms/community_meta_test.exs index 0e50d9728..20e150308 100644 --- a/test/groupher_server_web/query/cms/community_meta_test.exs +++ b/test/groupher_server_web/query/cms/community_meta_test.exs @@ -29,7 +29,6 @@ defmodule GroupherServer.Test.Query.CMS.CommunityMeta do } } """ - @tag :wip3 test "community have valid [thread]s_count in meta", ~m(guest_conn community_attrs user)a do {:ok, community} = CMS.create_community(community_attrs) diff --git a/test/groupher_server_web/query/cms/flags/posts_flags_test.exs b/test/groupher_server_web/query/cms/flags/posts_flags_test.exs index a54ac47c7..d8fdddfd8 100644 --- a/test/groupher_server_web/query/cms/flags/posts_flags_test.exs +++ b/test/groupher_server_web/query/cms/flags/posts_flags_test.exs @@ -48,11 +48,10 @@ defmodule GroupherServer.Test.Query.Flags.PostsFlags do } } """ - @tag :wip + test "if have pinned posts, the pinned posts should at the top of entries", ~m(guest_conn community post_m)a do variables = %{filter: %{community: community.raw}} - # variables = %{filter: %{}} results = guest_conn |> query_result(@query, variables, "pagedPosts") diff --git a/test/groupher_server_web/query/cms/paged_articles/paged_jobs_test.exs b/test/groupher_server_web/query/cms/paged_articles/paged_jobs_test.exs index d998388f6..ed7e369b0 100644 --- a/test/groupher_server_web/query/cms/paged_articles/paged_jobs_test.exs +++ b/test/groupher_server_web/query/cms/paged_articles/paged_jobs_test.exs @@ -13,9 +13,9 @@ defmodule GroupherServer.Test.Query.PagedArticles.PagedJobs do @page_size get_config(:general, :page_size) @cur_date Timex.now() - @last_week Timex.shift(Timex.beginning_of_week(@cur_date), days: -1, microseconds: -1) - @last_month Timex.shift(Timex.beginning_of_month(@cur_date), days: -7, microseconds: -1) - @last_year Timex.shift(Timex.beginning_of_year(@cur_date), days: -2, microseconds: -1) + @last_week Timex.shift(Timex.beginning_of_week(@cur_date), days: -1, seconds: -1) + @last_month Timex.shift(Timex.beginning_of_month(@cur_date), days: -7, seconds: -1) + @last_year Timex.shift(Timex.beginning_of_year(@cur_date), days: -2, seconds: -1) @today_count 15 @@ -28,14 +28,18 @@ defmodule GroupherServer.Test.Query.PagedArticles.PagedJobs do setup do {:ok, user} = db_insert(:user) - db_insert_multi(:job, @today_count) - db_insert(:job, %{title: "last week", inserted_at: @last_week}) + {:ok, job_last_week} = + db_insert(:job, %{title: "last week", inserted_at: @last_week, active_at: @last_week}) + db_insert(:job, %{title: "last month", inserted_at: @last_month}) - {:ok, job_last_year} = db_insert(:job, %{title: "last year", inserted_at: @last_year}) + {:ok, job_last_year} = + db_insert(:job, %{title: "last year", inserted_at: @last_year, active_at: @last_year}) + + db_insert_multi(:job, @today_count) guest_conn = simu_conn(:guest) - {:ok, ~m(guest_conn user job_last_year)a} + {:ok, ~m(guest_conn user job_last_week job_last_year)a} end describe "[query paged_jobs filter pagination]" do @@ -113,7 +117,6 @@ defmodule GroupherServer.Test.Query.PagedArticles.PagedJobs do assert not exist_in?(article_tag3, job["articleTags"], :string_key) end - @tag :wip2 test "should not have pined jobs when filter have article_tag or article_tags", ~m(guest_conn user)a do {:ok, community} = db_insert(:community) @@ -232,13 +235,14 @@ defmodule GroupherServer.Test.Query.PagedArticles.PagedJobs do end end - describe "[query paged_jobss filter sort]" do + describe "[query paged_jobs filter sort]" do @query """ query($filter: PagedJobsFilter!) { pagedJobs(filter: $filter) { entries { id inserted_at + active_at author { id nickname @@ -248,6 +252,7 @@ defmodule GroupherServer.Test.Query.PagedArticles.PagedJobs do } } """ + test "filter community should get jobs which belongs to that community", ~m(guest_conn user)a do {:ok, community} = db_insert(:community) @@ -260,18 +265,26 @@ defmodule GroupherServer.Test.Query.PagedArticles.PagedJobs do assert results["entries"] |> Enum.any?(&(&1["id"] == to_string(job.id))) end - @tag :skip_travis - test "filter sort should have default :desc_inserted", ~m(guest_conn)a do - variables = %{filter: %{}} + test "should have a active_at same with inserted_at", ~m(guest_conn user)a do + {:ok, community} = db_insert(:community) + {:ok, _job} = CMS.create_article(community, :job, mock_attrs(:job), user) + + variables = %{filter: %{community: community.raw}} results = guest_conn |> query_result(@query, variables, "pagedJobs") - inserted_timestamps = results["entries"] |> Enum.map(& &1["inserted_at"]) + job = results["entries"] |> List.first() + + assert job["inserted_at"] == job["active_at"] + end - {:ok, first_inserted_time, 0} = - inserted_timestamps |> List.first() |> DateTime.from_iso8601() + test "filter sort should have default :desc_active", ~m(guest_conn)a do + variables = %{filter: %{}} + results = guest_conn |> query_result(@query, variables, "pagedJobs") + active_timestamps = results["entries"] |> Enum.map(& &1["active_at"]) - {:ok, last_inserted_time, 0} = inserted_timestamps |> List.last() |> DateTime.from_iso8601() + {:ok, first_active_time, 0} = active_timestamps |> List.first() |> DateTime.from_iso8601() + {:ok, last_active_time, 0} = active_timestamps |> List.last() |> DateTime.from_iso8601() - assert :gt = DateTime.compare(first_inserted_time, last_inserted_time) + assert :gt = DateTime.compare(first_active_time, last_active_time) end @query """ @@ -381,4 +394,65 @@ defmodule GroupherServer.Test.Query.PagedArticles.PagedJobs do assert results["entries"] |> Enum.any?(&(&1["id"] != to_string(job2.id))) end end + + describe "[paged jobs active_at]" do + @query """ + query($filter: PagedJobsFilter!) { + pagedJobs(filter: $filter) { + entries { + id + insertedAt + activeAt + } + } + } + """ + + test "latest commented job should appear on top", ~m(guest_conn job_last_week user)a do + variables = %{filter: %{page: 1, size: 20}} + results = guest_conn |> query_result(@query, variables, "pagedJobs") + entries = results["entries"] + first_job = entries |> List.first() + assert first_job["id"] !== to_string(job_last_week.id) + + Process.sleep(1500) + {:ok, _comment} = CMS.create_article_comment(:job, job_last_week.id, "comment", user) + + results = guest_conn |> query_result(@query, variables, "pagedJobs") + entries = results["entries"] + first_job = entries |> List.first() + + assert first_job["id"] == to_string(job_last_week.id) + end + + test "comment on very old job have no effect", ~m(guest_conn job_last_year user)a do + variables = %{filter: %{page: 1, size: 20}} + + {:ok, _comment} = CMS.create_article_comment(:job, job_last_year.id, "comment", user) + + results = guest_conn |> query_result(@query, variables, "pagedJobs") + entries = results["entries"] + first_job = entries |> List.first() + + assert first_job["id"] !== to_string(job_last_year.id) + end + + test "latest job author commented job have no effect", ~m(guest_conn job_last_week)a do + variables = %{filter: %{page: 1, size: 20}} + + {:ok, _comment} = + CMS.create_article_comment( + :job, + job_last_week.id, + "comment", + job_last_week.author.user + ) + + results = guest_conn |> query_result(@query, variables, "pagedJobs") + entries = results["entries"] + first_job = entries |> List.first() + + assert first_job["id"] !== to_string(job_last_week.id) + end + end end diff --git a/test/groupher_server_web/query/cms/paged_articles/paged_posts_test.exs b/test/groupher_server_web/query/cms/paged_articles/paged_posts_test.exs index ebf37f9ae..21b699afc 100644 --- a/test/groupher_server_web/query/cms/paged_articles/paged_posts_test.exs +++ b/test/groupher_server_web/query/cms/paged_articles/paged_posts_test.exs @@ -13,9 +13,9 @@ defmodule GroupherServer.Test.Query.PagedArticles.PagedPosts do @page_size get_config(:general, :page_size) @cur_date Timex.now() - @last_week Timex.shift(Timex.beginning_of_week(@cur_date), days: -1, microseconds: -1) - @last_month Timex.shift(Timex.beginning_of_month(@cur_date), days: -1, microseconds: -1) - @last_year Timex.shift(Timex.beginning_of_year(@cur_date), days: -3, microseconds: -1) + @last_week Timex.shift(Timex.beginning_of_week(@cur_date), days: -1, seconds: -1) + @last_month Timex.shift(Timex.beginning_of_month(@cur_date), days: -1, seconds: -1) + @last_year Timex.shift(Timex.beginning_of_year(@cur_date), days: -3, seconds: -1) @today_count 15 @@ -29,14 +29,18 @@ defmodule GroupherServer.Test.Query.PagedArticles.PagedPosts do {:ok, user} = db_insert(:user) {:ok, post_last_month} = db_insert(:post, %{title: "last month", inserted_at: @last_month}) - {:ok, post1} = db_insert(:post, %{title: "last week", inserted_at: @last_week}) - {:ok, post_last_year} = db_insert(:post, %{title: "last year", inserted_at: @last_year}) + + {:ok, post_last_week} = + db_insert(:post, %{title: "last week", inserted_at: @last_week, active_at: @last_week}) + + {:ok, post_last_year} = + db_insert(:post, %{title: "last year", inserted_at: @last_year, active_at: @last_year}) db_insert_multi(:post, @today_count) guest_conn = simu_conn(:guest) - {:ok, ~m(guest_conn user post1 post_last_month post_last_year)a} + {:ok, ~m(guest_conn user post_last_week post_last_month post_last_year)a} end describe "[query paged_posts filter pagination]" do @@ -132,6 +136,7 @@ defmodule GroupherServer.Test.Query.PagedArticles.PagedPosts do entries { id inserted_at + active_at author { id nickname @@ -145,6 +150,7 @@ defmodule GroupherServer.Test.Query.PagedArticles.PagedPosts do } } """ + test "filter community should get posts which belongs to that community", ~m(guest_conn user)a do {:ok, community} = db_insert(:community) @@ -157,15 +163,24 @@ defmodule GroupherServer.Test.Query.PagedArticles.PagedPosts do assert results["entries"] |> Enum.any?(&(&1["id"] == to_string(post.id))) end - test "filter sort should have default :desc_inserted", ~m(guest_conn)a do - variables = %{filter: %{}} + test "should have a active_at same with inserted_at", ~m(guest_conn user)a do + {:ok, community} = db_insert(:community) + {:ok, _post} = CMS.create_article(community, :post, mock_attrs(:post), user) + + variables = %{filter: %{community: community.raw}} results = guest_conn |> query_result(@query, variables, "pagedPosts") - inserted_timestamps = results["entries"] |> Enum.map(& &1["inserted_at"]) + post = results["entries"] |> List.first() - {:ok, first_inserted_time, 0} = - inserted_timestamps |> List.first() |> DateTime.from_iso8601() + assert post["inserted_at"] == post["active_at"] + end - {:ok, last_inserted_time, 0} = inserted_timestamps |> List.last() |> DateTime.from_iso8601() + test "filter sort should have default :desc_active", ~m(guest_conn)a do + variables = %{filter: %{}} + results = guest_conn |> query_result(@query, variables, "pagedPosts") + active_timestamps = results["entries"] |> Enum.map(& &1["active_at"]) + + {:ok, first_inserted_time, 0} = active_timestamps |> List.first() |> DateTime.from_iso8601() + {:ok, last_inserted_time, 0} = active_timestamps |> List.last() |> DateTime.from_iso8601() assert :gt = DateTime.compare(first_inserted_time, last_inserted_time) end @@ -273,7 +288,6 @@ defmodule GroupherServer.Test.Query.PagedArticles.PagedPosts do assert results |> Map.get("totalCount") == expect_count end - @tag :skip_travis test "THIS_WEEK option should work", ~m(guest_conn)a do variables = %{filter: %{when: "THIS_WEEK"}} results = guest_conn |> query_result(@query, variables, "pagedPosts") @@ -288,4 +302,67 @@ defmodule GroupherServer.Test.Query.PagedArticles.PagedPosts do assert results["entries"] |> Enum.any?(&(&1["id"] != post_last_month.id)) end end + + describe "[paged posts active_at]" do + @query """ + query($filter: PagedPostsFilter!) { + pagedPosts(filter: $filter) { + entries { + id + insertedAt + activeAt + } + } + } + """ + @tag :wip2 + test "latest commented post should appear on top", ~m(guest_conn post_last_week user)a do + variables = %{filter: %{page: 1, size: 20}} + results = guest_conn |> query_result(@query, variables, "pagedPosts") + entries = results["entries"] + first_post = entries |> List.first() + assert first_post["id"] !== to_string(post_last_week.id) + + Process.sleep(1500) + {:ok, _comment} = CMS.create_article_comment(:post, post_last_week.id, "comment", user) + + results = guest_conn |> query_result(@query, variables, "pagedPosts") + entries = results["entries"] + first_post = entries |> List.first() + + assert first_post["id"] == to_string(post_last_week.id) + end + + @tag :wip2 + test "comment on very old post have no effect", ~m(guest_conn post_last_year user)a do + variables = %{filter: %{page: 1, size: 20}} + + {:ok, _comment} = CMS.create_article_comment(:post, post_last_year.id, "comment", user) + + results = guest_conn |> query_result(@query, variables, "pagedPosts") + entries = results["entries"] + first_post = entries |> List.first() + + assert first_post["id"] !== to_string(post_last_year.id) + end + + @tag :wip2 + test "latest post author commented post have no effect", ~m(guest_conn post_last_week)a do + variables = %{filter: %{page: 1, size: 20}} + + {:ok, _comment} = + CMS.create_article_comment( + :post, + post_last_week.id, + "comment", + post_last_week.author.user + ) + + results = guest_conn |> query_result(@query, variables, "pagedPosts") + entries = results["entries"] + first_post = entries |> List.first() + + assert first_post["id"] !== to_string(post_last_week.id) + end + end end diff --git a/test/groupher_server_web/query/cms/paged_articles/paged_repos_test.exs b/test/groupher_server_web/query/cms/paged_articles/paged_repos_test.exs index 1684aeaa6..cdd656b77 100644 --- a/test/groupher_server_web/query/cms/paged_articles/paged_repos_test.exs +++ b/test/groupher_server_web/query/cms/paged_articles/paged_repos_test.exs @@ -9,9 +9,9 @@ defmodule GroupherServer.Test.Query.PagedArticles.PagedRepos do @page_size get_config(:general, :page_size) @cur_date Timex.now() - @last_week Timex.shift(Timex.beginning_of_week(@cur_date), days: -1, microseconds: -1) - @last_month Timex.shift(Timex.beginning_of_month(@cur_date), days: -7, microseconds: -1) - @last_year Timex.shift(Timex.beginning_of_year(@cur_date), days: -2, microseconds: -1) + @last_week Timex.shift(Timex.beginning_of_week(@cur_date), days: -1, seconds: -1) + @last_month Timex.shift(Timex.beginning_of_month(@cur_date), days: -7, seconds: -1) + @last_year Timex.shift(Timex.beginning_of_year(@cur_date), days: -2, seconds: -1) @today_count 15 @@ -25,13 +25,18 @@ defmodule GroupherServer.Test.Query.PagedArticles.PagedRepos do {:ok, user} = db_insert(:user) db_insert_multi(:repo, @today_count) - db_insert(:repo, %{repo_name: "last week", inserted_at: @last_week}) + + {:ok, repo_last_week} = + db_insert(:repo, %{repo_name: "last week", inserted_at: @last_week, active_at: @last_week}) + db_insert(:repo, %{repo_name: "last month", inserted_at: @last_month}) - {:ok, repo_last_year} = db_insert(:repo, %{repo_name: "last year", inserted_at: @last_year}) + + {:ok, repo_last_year} = + db_insert(:repo, %{repo_name: "last year", inserted_at: @last_year, active_at: @last_year}) guest_conn = simu_conn(:guest) - {:ok, ~m(guest_conn user repo_last_year)a} + {:ok, ~m(guest_conn user repo_last_week repo_last_year)a} end describe "[query paged_repos filter pagination]" do @@ -176,6 +181,7 @@ defmodule GroupherServer.Test.Query.PagedArticles.PagedRepos do entries { id inserted_at + active_at author { id nickname @@ -201,18 +207,26 @@ defmodule GroupherServer.Test.Query.PagedArticles.PagedRepos do assert results["entries"] |> Enum.any?(&(&1["id"] == to_string(repo.id))) end - @tag :skip_travis - test "filter sort should have default :desc_inserted", ~m(guest_conn)a do - variables = %{filter: %{}} + test "should have a active_at same with inserted_at", ~m(guest_conn user)a do + {:ok, community} = db_insert(:community) + {:ok, _repo} = CMS.create_article(community, :repo, mock_attrs(:repo), user) + + variables = %{filter: %{community: community.raw}} results = guest_conn |> query_result(@query, variables, "pagedRepos") - inserted_timestamps = results["entries"] |> Enum.map(& &1["inserted_at"]) + repo = results["entries"] |> List.first() - {:ok, first_inserted_time, 0} = - inserted_timestamps |> List.first() |> DateTime.from_iso8601() + assert repo["inserted_at"] == repo["active_at"] + end - {:ok, last_inserted_time, 0} = inserted_timestamps |> List.last() |> DateTime.from_iso8601() + test "filter sort should have default :desc_active", ~m(guest_conn)a do + variables = %{filter: %{}} + results = guest_conn |> query_result(@query, variables, "pagedRepos") + active_timestamps = results["entries"] |> Enum.map(& &1["active_at"]) + + {:ok, first_active_time, 0} = active_timestamps |> List.first() |> DateTime.from_iso8601() + {:ok, last_active_time, 0} = active_timestamps |> List.last() |> DateTime.from_iso8601() - assert :gt = DateTime.compare(first_inserted_time, last_inserted_time) + assert :gt = DateTime.compare(first_active_time, last_active_time) end @query """ @@ -325,4 +339,64 @@ defmodule GroupherServer.Test.Query.PagedArticles.PagedRepos do assert first_count > last_count end end + + describe "[paged repos active_at]" do + @query """ + query($filter: PagedReposFilter!) { + pagedRepos(filter: $filter) { + entries { + id + insertedAt + activeAt + } + } + } + """ + test "latest commented repo should appear on top", ~m(guest_conn repo_last_week user)a do + variables = %{filter: %{page: 1, size: 20}} + results = guest_conn |> query_result(@query, variables, "pagedRepos") + entries = results["entries"] + first_repo = entries |> List.first() + assert first_repo["id"] !== to_string(repo_last_week.id) + + Process.sleep(1500) + {:ok, _comment} = CMS.create_article_comment(:repo, repo_last_week.id, "comment", user) + + results = guest_conn |> query_result(@query, variables, "pagedRepos") + entries = results["entries"] + first_repo = entries |> List.first() + + assert first_repo["id"] == to_string(repo_last_week.id) + end + + test "comment on very old repo have no effect", ~m(guest_conn repo_last_year user)a do + variables = %{filter: %{page: 1, size: 20}} + + {:ok, _comment} = CMS.create_article_comment(:repo, repo_last_year.id, "comment", user) + + results = guest_conn |> query_result(@query, variables, "pagedRepos") + entries = results["entries"] + first_repo = entries |> List.first() + + assert first_repo["id"] !== to_string(repo_last_year.id) + end + + test "latest repo author commented repo have no effect", ~m(guest_conn repo_last_week)a do + variables = %{filter: %{page: 1, size: 20}} + + {:ok, _comment} = + CMS.create_article_comment( + :repo, + repo_last_week.id, + "comment", + repo_last_week.author.user + ) + + results = guest_conn |> query_result(@query, variables, "pagedRepos") + entries = results["entries"] + first_repo = entries |> List.first() + + assert first_repo["id"] !== to_string(repo_last_week.id) + end + end end diff --git a/test/support/factory.ex b/test/support/factory.ex index db0c5e771..866586ab5 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -10,12 +10,14 @@ defmodule GroupherServer.Support.Factory do alias GroupherServer.Repo alias GroupherServer.{Accounts, CMS, Delivery} + @default_article_meta CMS.Embeds.ArticleMeta.default_meta() @default_emotions CMS.Embeds.ArticleCommentEmotion.default_emotions() defp mock_meta(:post) do body = Faker.Lorem.sentence(%Range{first: 80, last: 120}) %{ + meta: @default_article_meta, title: String.slice(body, 1, 49), body: body, digest: String.slice(body, 1, 150), @@ -27,7 +29,8 @@ defmodule GroupherServer.Support.Factory do mock(:community), mock(:community) ], - emotions: @default_emotions + emotions: @default_emotions, + active_at: Timex.shift(Timex.now(), seconds: -1) } end @@ -35,6 +38,7 @@ defmodule GroupherServer.Support.Factory do desc = Faker.Lorem.sentence(%Range{first: 15, last: 60}) %{ + meta: @default_article_meta, title: String.slice(desc, 1, 49), owner_name: "coderplanets", owner_url: "http://www.github.com/coderplanets", @@ -64,7 +68,8 @@ defmodule GroupherServer.Support.Factory do mock(:community), mock(:community) ], - emotions: @default_emotions + emotions: @default_emotions, + active_at: Timex.shift(Timex.now(), seconds: +1) } end @@ -103,6 +108,7 @@ defmodule GroupherServer.Support.Factory do body = Faker.Lorem.sentence(%Range{first: 80, last: 120}) %{ + meta: @default_article_meta, title: String.slice(body, 1, 49), company: Faker.Company.name(), body: body, @@ -115,7 +121,8 @@ defmodule GroupherServer.Support.Factory do communities: [ mock(:community) ], - emotions: @default_emotions + emotions: @default_emotions, + active_at: Timex.shift(Timex.now(), seconds: +1) } end @@ -319,9 +326,10 @@ defmodule GroupherServer.Support.Factory do Repo.insert(mock(factory_name, attributes)) end - def db_insert_multi(factory_name, count \\ 2) do + def db_insert_multi(factory_name, count, delay \\ 0) do results = Enum.reduce(1..count, [], fn _, acc -> + Process.sleep(delay) {:ok, value} = db_insert(factory_name) acc ++ [value] end)