github.com/bugraaydogar/snapd@v0.0.0-20210315170335-8c70bb858939/daemon/api_buy_unsupp_test.go (about)

     1  /*
     2   * Copyright (C) 2014-2020 Canonical Ltd
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU General Public License version 3 as
     6   * published by the Free Software Foundation.
     7   *
     8   * This program is distributed in the hope that it will be useful,
     9   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    10   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11   * GNU General Public License for more details.
    12   *
    13   * You should have received a copy of the GNU General Public License
    14   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15   *
    16   */
    17  
    18  package daemon_test
    19  
    20  import (
    21  	"bytes"
    22  	"fmt"
    23  	"net/http"
    24  
    25  	"gopkg.in/check.v1"
    26  
    27  	"github.com/snapcore/snapd/client"
    28  	"github.com/snapcore/snapd/daemon"
    29  	"github.com/snapcore/snapd/overlord/auth"
    30  	"github.com/snapcore/snapd/store"
    31  )
    32  
    33  var _ = check.Suite(&buySuite{})
    34  
    35  type buySuite struct {
    36  	apiBaseSuite
    37  
    38  	user *auth.UserState
    39  	err  error
    40  
    41  	buyOptions *client.BuyOptions
    42  	buyResult  *client.BuyResult
    43  }
    44  
    45  func (s *buySuite) Buy(options *client.BuyOptions, user *auth.UserState) (*client.BuyResult, error) {
    46  	s.pokeStateLock()
    47  
    48  	s.buyOptions = options
    49  	s.user = user
    50  	return s.buyResult, s.err
    51  }
    52  
    53  func (s *buySuite) ReadyToBuy(user *auth.UserState) error {
    54  	s.pokeStateLock()
    55  
    56  	s.user = user
    57  	return s.err
    58  }
    59  
    60  func (s *buySuite) SetUpTest(c *check.C) {
    61  	s.apiBaseSuite.SetUpTest(c)
    62  
    63  	s.user = nil
    64  	s.err = nil
    65  	s.buyOptions = nil
    66  	s.buyResult = nil
    67  
    68  	s.daemonWithStore(c, s)
    69  }
    70  
    71  const validBuyInput = `{
    72  		  "snap-id": "the-snap-id-1234abcd",
    73  		  "snap-name": "the snap name",
    74  		  "price": 1.23,
    75  		  "currency": "EUR"
    76  		}`
    77  
    78  var validBuyOptions = &client.BuyOptions{
    79  	SnapID:   "the-snap-id-1234abcd",
    80  	Price:    1.23,
    81  	Currency: "EUR",
    82  }
    83  
    84  var buyTests = []struct {
    85  	input                string
    86  	result               *client.BuyResult
    87  	err                  error
    88  	expectedStatus       int
    89  	expectedResult       interface{}
    90  	expectedResponseType daemon.ResponseType
    91  	expectedBuyOptions   *client.BuyOptions
    92  }{
    93  	{
    94  		// Success
    95  		input: validBuyInput,
    96  		result: &client.BuyResult{
    97  			State: "Complete",
    98  		},
    99  		expectedStatus: 200,
   100  		expectedResult: &client.BuyResult{
   101  			State: "Complete",
   102  		},
   103  		expectedResponseType: daemon.ResponseTypeSync,
   104  		expectedBuyOptions:   validBuyOptions,
   105  	},
   106  	{
   107  		// Fail with internal error
   108  		input: `{
   109  		  "snap-id": "the-snap-id-1234abcd",
   110  		  "price": 1.23,
   111  		  "currency": "EUR"
   112  		}`,
   113  		err:                  fmt.Errorf("internal error banana"),
   114  		expectedStatus:       500,
   115  		expectedResponseType: daemon.ResponseTypeError,
   116  		expectedResult: &daemon.ErrorResult{
   117  			Message: "internal error banana",
   118  		},
   119  		expectedBuyOptions: &client.BuyOptions{
   120  			SnapID:   "the-snap-id-1234abcd",
   121  			Price:    1.23,
   122  			Currency: "EUR",
   123  		},
   124  	},
   125  	{
   126  		// Fail with unauthenticated error
   127  		input:                validBuyInput,
   128  		err:                  store.ErrUnauthenticated,
   129  		expectedStatus:       400,
   130  		expectedResponseType: daemon.ResponseTypeError,
   131  		expectedResult: &daemon.ErrorResult{
   132  			Message: "you need to log in first",
   133  			Kind:    "login-required",
   134  		},
   135  		expectedBuyOptions: validBuyOptions,
   136  	},
   137  	{
   138  		// Fail with TOS not accepted
   139  		input:                validBuyInput,
   140  		err:                  store.ErrTOSNotAccepted,
   141  		expectedStatus:       400,
   142  		expectedResponseType: daemon.ResponseTypeError,
   143  		expectedResult: &daemon.ErrorResult{
   144  			Message: "terms of service not accepted",
   145  			Kind:    "terms-not-accepted",
   146  		},
   147  		expectedBuyOptions: validBuyOptions,
   148  	},
   149  	{
   150  		// Fail with no payment methods
   151  		input:                validBuyInput,
   152  		err:                  store.ErrNoPaymentMethods,
   153  		expectedStatus:       400,
   154  		expectedResponseType: daemon.ResponseTypeError,
   155  		expectedResult: &daemon.ErrorResult{
   156  			Message: "no payment methods",
   157  			Kind:    "no-payment-methods",
   158  		},
   159  		expectedBuyOptions: validBuyOptions,
   160  	},
   161  	{
   162  		// Fail with payment declined
   163  		input:                validBuyInput,
   164  		err:                  store.ErrPaymentDeclined,
   165  		expectedStatus:       400,
   166  		expectedResponseType: daemon.ResponseTypeError,
   167  		expectedResult: &daemon.ErrorResult{
   168  			Message: "payment declined",
   169  			Kind:    "payment-declined",
   170  		},
   171  		expectedBuyOptions: validBuyOptions,
   172  	},
   173  }
   174  
   175  func (s *buySuite) TestBuySnap(c *check.C) {
   176  	user := &auth.UserState{
   177  		Username: "username",
   178  		Email:    "email@test.com",
   179  	}
   180  
   181  	for _, test := range buyTests {
   182  		s.buyResult = test.result
   183  		s.err = test.err
   184  
   185  		buf := bytes.NewBufferString(test.input)
   186  		req, err := http.NewRequest("POST", "/v2/buy", buf)
   187  		c.Assert(err, check.IsNil)
   188  
   189  		rsp := s.req(c, req, user).(*daemon.Resp)
   190  
   191  		c.Check(rsp.Status, check.Equals, test.expectedStatus)
   192  		c.Check(rsp.Type, check.Equals, test.expectedResponseType)
   193  		c.Assert(rsp.Result, check.FitsTypeOf, test.expectedResult)
   194  		c.Check(rsp.Result, check.DeepEquals, test.expectedResult)
   195  
   196  		c.Check(s.buyOptions, check.DeepEquals, test.expectedBuyOptions)
   197  		c.Check(s.user, check.Equals, user)
   198  	}
   199  }
   200  
   201  var readyToBuyTests = []struct {
   202  	input    error
   203  	status   int
   204  	respType interface{}
   205  	response interface{}
   206  }{
   207  	{
   208  		// Success
   209  		input:    nil,
   210  		status:   200,
   211  		respType: daemon.ResponseTypeSync,
   212  		response: true,
   213  	},
   214  	{
   215  		// Not accepted TOS
   216  		input:    store.ErrTOSNotAccepted,
   217  		status:   400,
   218  		respType: daemon.ResponseTypeError,
   219  		response: &daemon.ErrorResult{
   220  			Message: "terms of service not accepted",
   221  			Kind:    client.ErrorKindTermsNotAccepted,
   222  		},
   223  	},
   224  	{
   225  		// No payment methods
   226  		input:    store.ErrNoPaymentMethods,
   227  		status:   400,
   228  		respType: daemon.ResponseTypeError,
   229  		response: &daemon.ErrorResult{
   230  			Message: "no payment methods",
   231  			Kind:    client.ErrorKindNoPaymentMethods,
   232  		},
   233  	},
   234  }
   235  
   236  func (s *buySuite) TestReadyToBuy(c *check.C) {
   237  	user := &auth.UserState{
   238  		Username: "username",
   239  		Email:    "email@test.com",
   240  	}
   241  
   242  	for _, test := range readyToBuyTests {
   243  		s.err = test.input
   244  
   245  		req, err := http.NewRequest("GET", "/v2/buy/ready", nil)
   246  		c.Assert(err, check.IsNil)
   247  
   248  		rsp := s.req(c, req, user).(*daemon.Resp)
   249  		c.Check(rsp.Status, check.Equals, test.status)
   250  		c.Check(rsp.Type, check.Equals, test.respType)
   251  		c.Assert(rsp.Result, check.FitsTypeOf, test.response)
   252  		c.Check(rsp.Result, check.DeepEquals, test.response)
   253  	}
   254  }