feat: add global system notices and Beijing order time display
Deploy olons-server production / deploy (push) Successful in 3m12s
Deploy olons-server production / deploy (push) Successful in 3m12s
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
func TestPendingNoticeAudienceAndReadAcknowledgement(t *testing.T) {
|
||||
dsn := os.Getenv("OLONS_TEST_MYSQL_DSN")
|
||||
if dsn == "" {
|
||||
t.Skip("set OLONS_TEST_MYSQL_DSN to run the notice integration test")
|
||||
}
|
||||
db, err := sqlx.Connect("mysql", dsn)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
db.SetMaxOpenConns(1)
|
||||
db.SetMaxIdleConns(1)
|
||||
t.Cleanup(func() { _ = db.Close() })
|
||||
// Connection-local temporary tables shadow the real tables without changing application data.
|
||||
for _, statement := range []string{
|
||||
`CREATE TEMPORARY TABLE hg_app_member_notice (
|
||||
id BIGINT PRIMARY KEY, tenant_id BIGINT, member_id BIGINT,
|
||||
title VARCHAR(120), content TEXT, source_type INT, notice_status INT,
|
||||
start_at DATETIME(3), end_at DATETIME(3), created_at DATETIME(3))`,
|
||||
`CREATE TEMPORARY TABLE hg_app_member_notice_read (
|
||||
id BIGINT PRIMARY KEY AUTO_INCREMENT, tenant_id BIGINT, notice_id BIGINT,
|
||||
member_id BIGINT, read_at DATETIME(3), created_at DATETIME(3),
|
||||
UNIQUE KEY (tenant_id, notice_id, member_id))`,
|
||||
} {
|
||||
if _, err := db.Exec(statement); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
now := time.Now()
|
||||
for _, notice := range []struct {
|
||||
id, tenantID, memberID int64
|
||||
status int
|
||||
start, end time.Time
|
||||
}{
|
||||
{1, 0, 9, 1, now.Add(-2 * time.Hour), now.Add(time.Hour)},
|
||||
{2, 0, 9, 1, now.Add(-time.Hour), now.Add(time.Hour)},
|
||||
{3, 0, 10, 1, now.Add(-time.Hour), now.Add(time.Hour)},
|
||||
{4, 1, 9, 1, now.Add(-time.Hour), now.Add(time.Hour)},
|
||||
{5, 0, 0, 1, now.Add(-time.Hour), now.Add(time.Hour)},
|
||||
{6, 0, 9, 2, now.Add(-time.Hour), now.Add(time.Hour)},
|
||||
{7, 0, 9, 1, now.Add(-2 * time.Hour), now.Add(-time.Hour)},
|
||||
{8, 0, 9, 1, now.Add(time.Hour), now.Add(2 * time.Hour)},
|
||||
} {
|
||||
_, err := db.Exec(`INSERT INTO hg_app_member_notice
|
||||
(id,tenant_id,member_id,title,content,source_type,notice_status,start_at,end_at,created_at)
|
||||
VALUES (?,?,?,'系统通知','通知内容',1,?,?,?,?)`, notice.id, notice.tenantID, notice.memberID,
|
||||
notice.status, formatNoticeBusinessTime(notice.start), formatNoticeBusinessTime(notice.end), formatNoticeBusinessTime(now))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
ctx := context.Background()
|
||||
s := &Store{db: db}
|
||||
for _, expectedID := range []int64{1, 2} {
|
||||
notice, err := s.NextUnreadMemberNotice(ctx, 0, 9)
|
||||
if err != nil || notice == nil || notice.ID != expectedID {
|
||||
t.Fatalf("pending notice = %+v, error = %v, want id %d", notice, err, expectedID)
|
||||
}
|
||||
if err := s.MarkMemberNoticeRead(ctx, 0, 9, expectedID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
if notice, err := s.NextUnreadMemberNotice(ctx, 0, 9); err != nil || notice != nil {
|
||||
t.Fatalf("read, expired, revoked, foreign and broadcast notices must not pop up: %+v, %v", notice, err)
|
||||
}
|
||||
for _, forbiddenID := range []int64{3, 4} {
|
||||
if err := s.MarkMemberNoticeRead(ctx, 0, 9, forbiddenID); !errors.Is(err, ErrResourceNotFound) {
|
||||
t.Fatalf("reading foreign notice %d: error = %v", forbiddenID, err)
|
||||
}
|
||||
}
|
||||
if notice, err := s.NextUnreadMemberNotice(ctx, 0, 10); err != nil || notice == nil || notice.ID != 3 {
|
||||
t.Fatalf("other recipient must retain their unread notice: %+v, %v", notice, err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user