You've already forked focalboard
							
							
				mirror of
				https://github.com/mattermost/focalboard.git
				synced 2025-10-31 00:17:42 +02:00 
			
		
		
		
	* initial commit for channel permissions * add test * check for write post when returning channels * lint fix * fix test --------- Co-authored-by: Mattermost Build <build@mattermost.com>
		
			
				
	
	
		
			563 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			563 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package integrationtests
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"net/http"
 | |
| 	"os"
 | |
| 	"testing"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/mattermost/focalboard/server/client"
 | |
| 	"github.com/mattermost/focalboard/server/model"
 | |
| 	"github.com/mattermost/focalboard/server/server"
 | |
| 	"github.com/mattermost/focalboard/server/services/auth"
 | |
| 	"github.com/mattermost/focalboard/server/services/config"
 | |
| 	"github.com/mattermost/focalboard/server/services/permissions/localpermissions"
 | |
| 	"github.com/mattermost/focalboard/server/services/permissions/mmpermissions"
 | |
| 	"github.com/mattermost/focalboard/server/services/store"
 | |
| 	"github.com/mattermost/focalboard/server/services/store/sqlstore"
 | |
| 	"github.com/mattermost/focalboard/server/utils"
 | |
| 
 | |
| 	mmModel "github.com/mattermost/mattermost-server/v6/model"
 | |
| 	"github.com/mattermost/mattermost-server/v6/shared/mlog"
 | |
| 
 | |
| 	"github.com/stretchr/testify/require"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	user1Username = "user1"
 | |
| 	user2Username = "user2"
 | |
| 	password      = "Pa$$word"
 | |
| 	testTeamID    = "team-id"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	userAnon         string = "anon"
 | |
| 	userNoTeamMember string = "no-team-member"
 | |
| 	userTeamMember   string = "team-member"
 | |
| 	userViewer       string = "viewer"
 | |
| 	userCommenter    string = "commenter"
 | |
| 	userEditor       string = "editor"
 | |
| 	userAdmin        string = "admin"
 | |
| 	userGuest        string = "guest"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	userAnonID         = userAnon
 | |
| 	userNoTeamMemberID = userNoTeamMember
 | |
| 	userTeamMemberID   = userTeamMember
 | |
| 	userViewerID       = userViewer
 | |
| 	userCommenterID    = userCommenter
 | |
| 	userEditorID       = userEditor
 | |
| 	userAdminID        = userAdmin
 | |
| 	userGuestID        = userGuest
 | |
| )
 | |
| 
 | |
| type LicenseType int
 | |
| 
 | |
| const (
 | |
| 	LicenseNone         LicenseType = iota // 0
 | |
| 	LicenseProfessional                    // 1
 | |
| 	LicenseEnterprise                      // 2
 | |
| )
 | |
| 
 | |
| type TestHelper struct {
 | |
| 	T       *testing.T
 | |
| 	Server  *server.Server
 | |
| 	Client  *client.Client
 | |
| 	Client2 *client.Client
 | |
| 
 | |
| 	origEnvUnitTesting string
 | |
| }
 | |
| 
 | |
| type FakePermissionPluginAPI struct{}
 | |
| 
 | |
| func (*FakePermissionPluginAPI) HasPermissionTo(userID string, permission *mmModel.Permission) bool {
 | |
| 	return userID == userAdmin
 | |
| }
 | |
| 
 | |
| func (*FakePermissionPluginAPI) HasPermissionToTeam(userID string, teamID string, permission *mmModel.Permission) bool {
 | |
| 	if permission.Id == model.PermissionManageTeam.Id {
 | |
| 		return false
 | |
| 	}
 | |
| 	if userID == userNoTeamMember {
 | |
| 		return false
 | |
| 	}
 | |
| 	if teamID == "empty-team" {
 | |
| 		return false
 | |
| 	}
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| func (*FakePermissionPluginAPI) HasPermissionToChannel(userID string, channelID string, permission *mmModel.Permission) bool {
 | |
| 	return channelID == "valid-channel-id" || channelID == "valid-channel-id-2"
 | |
| }
 | |
| 
 | |
| func getTestConfig() (*config.Configuration, error) {
 | |
| 	dbType, connectionString, err := sqlstore.PrepareNewTestDatabase()
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	logging := `
 | |
| 	{
 | |
| 		"testing": {
 | |
| 			"type": "console",
 | |
| 			"options": {
 | |
| 				"out": "stdout"
 | |
| 			},
 | |
| 			"format": "plain",
 | |
| 			"format_options": {
 | |
| 				"delim": "  "
 | |
| 			},
 | |
| 			"levels": [
 | |
| 				{"id": 5, "name": "debug"},
 | |
| 				{"id": 4, "name": "info"},
 | |
| 				{"id": 3, "name": "warn"},
 | |
| 				{"id": 2, "name": "error", "stacktrace": true},
 | |
| 				{"id": 1, "name": "fatal", "stacktrace": true},
 | |
| 				{"id": 0, "name": "panic", "stacktrace": true}
 | |
| 			]
 | |
| 		}
 | |
| 	}`
 | |
| 
 | |
| 	return &config.Configuration{
 | |
| 		ServerRoot:        "http://localhost:8888",
 | |
| 		Port:              8888,
 | |
| 		DBType:            dbType,
 | |
| 		DBConfigString:    connectionString,
 | |
| 		DBTablePrefix:     "test_",
 | |
| 		WebPath:           "./pack",
 | |
| 		FilesDriver:       "local",
 | |
| 		FilesPath:         "./files",
 | |
| 		LoggingCfgJSON:    logging,
 | |
| 		SessionExpireTime: int64(30 * time.Second),
 | |
| 		AuthMode:          "native",
 | |
| 	}, nil
 | |
| }
 | |
| 
 | |
| func newTestServer(singleUserToken string) *server.Server {
 | |
| 	return newTestServerWithLicense(singleUserToken, LicenseNone)
 | |
| }
 | |
| 
 | |
| func newTestServerWithLicense(singleUserToken string, licenseType LicenseType) *server.Server {
 | |
| 	cfg, err := getTestConfig()
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 
 | |
| 	logger, _ := mlog.NewLogger()
 | |
| 	if err = logger.Configure("", cfg.LoggingCfgJSON, nil); err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 	singleUser := len(singleUserToken) > 0
 | |
| 	innerStore, err := server.NewStore(cfg, singleUser, logger)
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 
 | |
| 	var db store.Store
 | |
| 
 | |
| 	switch licenseType {
 | |
| 	case LicenseProfessional:
 | |
| 		db = NewTestProfessionalStore(innerStore)
 | |
| 	case LicenseEnterprise:
 | |
| 		db = NewTestEnterpriseStore(innerStore)
 | |
| 	case LicenseNone:
 | |
| 		fallthrough
 | |
| 	default:
 | |
| 		db = innerStore
 | |
| 	}
 | |
| 
 | |
| 	permissionsService := localpermissions.New(db, logger)
 | |
| 
 | |
| 	params := server.Params{
 | |
| 		Cfg:                cfg,
 | |
| 		SingleUserToken:    singleUserToken,
 | |
| 		DBStore:            db,
 | |
| 		Logger:             logger,
 | |
| 		PermissionsService: permissionsService,
 | |
| 	}
 | |
| 
 | |
| 	srv, err := server.New(params)
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 
 | |
| 	return srv
 | |
| }
 | |
| 
 | |
| func NewTestServerPluginMode() *server.Server {
 | |
| 	cfg, err := getTestConfig()
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 	cfg.AuthMode = "mattermost"
 | |
| 	cfg.EnablePublicSharedBoards = true
 | |
| 
 | |
| 	logger, _ := mlog.NewLogger()
 | |
| 	if err = logger.Configure("", cfg.LoggingCfgJSON, nil); err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 	innerStore, err := server.NewStore(cfg, false, logger)
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 
 | |
| 	db := NewPluginTestStore(innerStore)
 | |
| 
 | |
| 	permissionsService := mmpermissions.New(db, &FakePermissionPluginAPI{}, logger)
 | |
| 
 | |
| 	params := server.Params{
 | |
| 		Cfg:                cfg,
 | |
| 		DBStore:            db,
 | |
| 		Logger:             logger,
 | |
| 		PermissionsService: permissionsService,
 | |
| 	}
 | |
| 
 | |
| 	srv, err := server.New(params)
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 
 | |
| 	return srv
 | |
| }
 | |
| 
 | |
| func newTestServerLocalMode() *server.Server {
 | |
| 	cfg, err := getTestConfig()
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 	cfg.EnablePublicSharedBoards = true
 | |
| 
 | |
| 	logger, _ := mlog.NewLogger()
 | |
| 	if err = logger.Configure("", cfg.LoggingCfgJSON, nil); err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 
 | |
| 	db, err := server.NewStore(cfg, false, logger)
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 
 | |
| 	permissionsService := localpermissions.New(db, logger)
 | |
| 
 | |
| 	params := server.Params{
 | |
| 		Cfg:                cfg,
 | |
| 		DBStore:            db,
 | |
| 		Logger:             logger,
 | |
| 		PermissionsService: permissionsService,
 | |
| 	}
 | |
| 
 | |
| 	srv, err := server.New(params)
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 
 | |
| 	// Reduce password has strength for unit tests to dramatically speed up account creation and login
 | |
| 	auth.PasswordHashStrength = 4
 | |
| 
 | |
| 	return srv
 | |
| }
 | |
| 
 | |
| func SetupTestHelperWithToken(t *testing.T) *TestHelper {
 | |
| 	origUnitTesting := os.Getenv("FOCALBOARD_UNIT_TESTING")
 | |
| 	os.Setenv("FOCALBOARD_UNIT_TESTING", "1")
 | |
| 
 | |
| 	sessionToken := "TESTTOKEN"
 | |
| 
 | |
| 	th := &TestHelper{
 | |
| 		T:                  t,
 | |
| 		origEnvUnitTesting: origUnitTesting,
 | |
| 	}
 | |
| 
 | |
| 	th.Server = newTestServer(sessionToken)
 | |
| 	th.Client = client.NewClient(th.Server.Config().ServerRoot, sessionToken)
 | |
| 	th.Client2 = client.NewClient(th.Server.Config().ServerRoot, sessionToken)
 | |
| 	return th
 | |
| }
 | |
| 
 | |
| func SetupTestHelper(t *testing.T) *TestHelper {
 | |
| 	return SetupTestHelperWithLicense(t, LicenseNone)
 | |
| }
 | |
| 
 | |
| func SetupTestHelperPluginMode(t *testing.T) *TestHelper {
 | |
| 	origUnitTesting := os.Getenv("FOCALBOARD_UNIT_TESTING")
 | |
| 	os.Setenv("FOCALBOARD_UNIT_TESTING", "1")
 | |
| 
 | |
| 	th := &TestHelper{
 | |
| 		T:                  t,
 | |
| 		origEnvUnitTesting: origUnitTesting,
 | |
| 	}
 | |
| 
 | |
| 	th.Server = NewTestServerPluginMode()
 | |
| 	th.Start()
 | |
| 	return th
 | |
| }
 | |
| 
 | |
| func SetupTestHelperLocalMode(t *testing.T) *TestHelper {
 | |
| 	origUnitTesting := os.Getenv("FOCALBOARD_UNIT_TESTING")
 | |
| 	os.Setenv("FOCALBOARD_UNIT_TESTING", "1")
 | |
| 
 | |
| 	th := &TestHelper{
 | |
| 		T:                  t,
 | |
| 		origEnvUnitTesting: origUnitTesting,
 | |
| 	}
 | |
| 
 | |
| 	th.Server = newTestServerLocalMode()
 | |
| 	th.Start()
 | |
| 	return th
 | |
| }
 | |
| 
 | |
| func SetupTestHelperWithLicense(t *testing.T, licenseType LicenseType) *TestHelper {
 | |
| 	origUnitTesting := os.Getenv("FOCALBOARD_UNIT_TESTING")
 | |
| 	os.Setenv("FOCALBOARD_UNIT_TESTING", "1")
 | |
| 
 | |
| 	th := &TestHelper{
 | |
| 		T:                  t,
 | |
| 		origEnvUnitTesting: origUnitTesting,
 | |
| 	}
 | |
| 
 | |
| 	th.Server = newTestServerWithLicense("", licenseType)
 | |
| 	th.Client = client.NewClient(th.Server.Config().ServerRoot, "")
 | |
| 	th.Client2 = client.NewClient(th.Server.Config().ServerRoot, "")
 | |
| 	return th
 | |
| }
 | |
| 
 | |
| // Start starts the test server and ensures that it's correctly
 | |
| // responding to requests before returning.
 | |
| func (th *TestHelper) Start() *TestHelper {
 | |
| 	go func() {
 | |
| 		if err := th.Server.Start(); err != nil {
 | |
| 			panic(err)
 | |
| 		}
 | |
| 	}()
 | |
| 
 | |
| 	for {
 | |
| 		URL := th.Server.Config().ServerRoot
 | |
| 		th.Server.Logger().Info("Polling server", mlog.String("url", URL))
 | |
| 		resp, err := http.Get(URL) //nolint:gosec
 | |
| 		if err != nil {
 | |
| 			th.Server.Logger().Error("Polling failed", mlog.Err(err))
 | |
| 			time.Sleep(100 * time.Millisecond)
 | |
| 			continue
 | |
| 		}
 | |
| 		resp.Body.Close()
 | |
| 
 | |
| 		// Currently returns 404
 | |
| 		// if resp.StatusCode != http.StatusOK {
 | |
| 		// 	th.Server.Logger().Error("Not OK", mlog.Int("statusCode", resp.StatusCode))
 | |
| 		// 	continue
 | |
| 		// }
 | |
| 
 | |
| 		// Reached this point: server is up and running!
 | |
| 		th.Server.Logger().Info("Server ping OK", mlog.Int("statusCode", resp.StatusCode))
 | |
| 
 | |
| 		break
 | |
| 	}
 | |
| 
 | |
| 	return th
 | |
| }
 | |
| 
 | |
| // InitBasic starts the test server and initializes the clients of the
 | |
| // helper, registering them and logging them into the system.
 | |
| func (th *TestHelper) InitBasic() *TestHelper {
 | |
| 	// Reduce password has strength for unit tests to dramatically speed up account creation and login
 | |
| 	auth.PasswordHashStrength = 4
 | |
| 
 | |
| 	th.Start()
 | |
| 
 | |
| 	// user1
 | |
| 	th.RegisterAndLogin(th.Client, user1Username, "user1@sample.com", password, "")
 | |
| 
 | |
| 	// get token
 | |
| 	team, resp := th.Client.GetTeam(model.GlobalTeamID)
 | |
| 	th.CheckOK(resp)
 | |
| 	require.NotNil(th.T, team)
 | |
| 	require.NotNil(th.T, team.SignupToken)
 | |
| 
 | |
| 	// user2
 | |
| 	th.RegisterAndLogin(th.Client2, user2Username, "user2@sample.com", password, team.SignupToken)
 | |
| 
 | |
| 	return th
 | |
| }
 | |
| 
 | |
| var ErrRegisterFail = errors.New("register failed")
 | |
| 
 | |
| func (th *TestHelper) TearDown() {
 | |
| 	os.Setenv("FOCALBOARD_UNIT_TESTING", th.origEnvUnitTesting)
 | |
| 
 | |
| 	logger := th.Server.Logger()
 | |
| 
 | |
| 	if l, ok := logger.(*mlog.Logger); ok {
 | |
| 		defer func() { _ = l.Shutdown() }()
 | |
| 	}
 | |
| 
 | |
| 	err := th.Server.Shutdown()
 | |
| 	if err != nil {
 | |
| 		panic(err)
 | |
| 	}
 | |
| 
 | |
| 	os.RemoveAll(th.Server.Config().FilesPath)
 | |
| 
 | |
| 	if err := os.Remove(th.Server.Config().DBConfigString); err == nil {
 | |
| 		logger.Debug("Removed test database", mlog.String("file", th.Server.Config().DBConfigString))
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) RegisterAndLogin(client *client.Client, username, email, password, token string) {
 | |
| 	req := &model.RegisterRequest{
 | |
| 		Username: username,
 | |
| 		Email:    email,
 | |
| 		Password: password,
 | |
| 		Token:    token,
 | |
| 	}
 | |
| 
 | |
| 	success, resp := th.Client.Register(req)
 | |
| 	th.CheckOK(resp)
 | |
| 	require.True(th.T, success)
 | |
| 
 | |
| 	th.Login(client, username, password)
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) Login(client *client.Client, username, password string) {
 | |
| 	req := &model.LoginRequest{
 | |
| 		Type:     "normal",
 | |
| 		Username: username,
 | |
| 		Password: password,
 | |
| 	}
 | |
| 	data, resp := client.Login(req)
 | |
| 	th.CheckOK(resp)
 | |
| 	require.NotNil(th.T, data)
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) Login1() {
 | |
| 	th.Login(th.Client, user1Username, password)
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) Login2() {
 | |
| 	th.Login(th.Client2, user2Username, password)
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) Logout(client *client.Client) {
 | |
| 	client.Token = ""
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) Me(client *client.Client) *model.User {
 | |
| 	user, resp := client.GetMe()
 | |
| 	th.CheckOK(resp)
 | |
| 	require.NotNil(th.T, user)
 | |
| 	return user
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) CreateBoard(teamID string, boardType model.BoardType) *model.Board {
 | |
| 	newBoard := &model.Board{
 | |
| 		TeamID: teamID,
 | |
| 		Type:   boardType,
 | |
| 	}
 | |
| 	board, resp := th.Client.CreateBoard(newBoard)
 | |
| 	th.CheckOK(resp)
 | |
| 	return board
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) CreateBoards(teamID string, boardType model.BoardType, count int) []*model.Board {
 | |
| 	boards := make([]*model.Board, 0, count)
 | |
| 
 | |
| 	for i := 0; i < count; i++ {
 | |
| 		board := th.CreateBoard(teamID, boardType)
 | |
| 		boards = append(boards, board)
 | |
| 	}
 | |
| 	return boards
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) CreateCategory(category model.Category) *model.Category {
 | |
| 	cat, resp := th.Client.CreateCategory(category)
 | |
| 	th.CheckOK(resp)
 | |
| 	return cat
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) UpdateCategoryBoard(teamID, categoryID, boardID string) {
 | |
| 	response := th.Client.UpdateCategoryBoard(teamID, categoryID, boardID)
 | |
| 	th.CheckOK(response)
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) CreateBoardAndCards(teamdID string, boardType model.BoardType, numCards int) (*model.Board, []*model.Card) {
 | |
| 	board := th.CreateBoard(teamdID, boardType)
 | |
| 	cards := make([]*model.Card, 0, numCards)
 | |
| 	for i := 0; i < numCards; i++ {
 | |
| 		card := &model.Card{
 | |
| 			Title:        fmt.Sprintf("test card %d", i+1),
 | |
| 			ContentOrder: []string{utils.NewID(utils.IDTypeBlock), utils.NewID(utils.IDTypeBlock), utils.NewID(utils.IDTypeBlock)},
 | |
| 			Icon:         "😱",
 | |
| 			Properties:   th.MakeCardProps(5),
 | |
| 		}
 | |
| 		newCard, resp := th.Client.CreateCard(board.ID, card, true)
 | |
| 		th.CheckOK(resp)
 | |
| 		cards = append(cards, newCard)
 | |
| 	}
 | |
| 	return board, cards
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) MakeCardProps(count int) map[string]any {
 | |
| 	props := make(map[string]any)
 | |
| 	for i := 0; i < count; i++ {
 | |
| 		props[utils.NewID(utils.IDTypeBlock)] = utils.NewID(utils.IDTypeBlock)
 | |
| 	}
 | |
| 	return props
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) GetUserCategoryBoards(teamID string) []model.CategoryBoards {
 | |
| 	categoryBoards, response := th.Client.GetUserCategoryBoards(teamID)
 | |
| 	th.CheckOK(response)
 | |
| 	return categoryBoards
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) DeleteCategory(teamID, categoryID string) {
 | |
| 	response := th.Client.DeleteCategory(teamID, categoryID)
 | |
| 	th.CheckOK(response)
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) GetUser1() *model.User {
 | |
| 	return th.Me(th.Client)
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) GetUser2() *model.User {
 | |
| 	return th.Me(th.Client2)
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) CheckOK(r *client.Response) {
 | |
| 	require.Equal(th.T, http.StatusOK, r.StatusCode)
 | |
| 	require.NoError(th.T, r.Error)
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) CheckBadRequest(r *client.Response) {
 | |
| 	require.Equal(th.T, http.StatusBadRequest, r.StatusCode)
 | |
| 	require.Error(th.T, r.Error)
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) CheckNotFound(r *client.Response) {
 | |
| 	require.Equal(th.T, http.StatusNotFound, r.StatusCode)
 | |
| 	require.Error(th.T, r.Error)
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) CheckUnauthorized(r *client.Response) {
 | |
| 	require.Equal(th.T, http.StatusUnauthorized, r.StatusCode)
 | |
| 	require.Error(th.T, r.Error)
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) CheckForbidden(r *client.Response) {
 | |
| 	require.Equal(th.T, http.StatusForbidden, r.StatusCode)
 | |
| 	require.Error(th.T, r.Error)
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) CheckRequestEntityTooLarge(r *client.Response) {
 | |
| 	require.Equal(th.T, http.StatusRequestEntityTooLarge, r.StatusCode)
 | |
| 	require.Error(th.T, r.Error)
 | |
| }
 | |
| 
 | |
| func (th *TestHelper) CheckNotImplemented(r *client.Response) {
 | |
| 	require.Equal(th.T, http.StatusNotImplemented, r.StatusCode)
 | |
| 	require.Error(th.T, r.Error)
 | |
| }
 |