86 lines
3.2 KiB
Go
86 lines
3.2 KiB
Go
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)
|
|
}
|
|
}
|