<commit_before>RSpec.describe Shore::Client::Tokens::AccessToken do
  let(:exp) { (Time.now.utc + 2.days).beginning_of_day }
  let(:algorithm) { 'HS256' }
  let(:public_key) { 'secret' }
  let(:private_key) { 'secret' }
  let(:member) { member_merchant }
  let(:merchant_token) do
    merchant_account_token(SecureRandom.uuid, [member])
  end
  let(:valid_jwt_payload) do
    described_class.new(
      data: merchant_token,
      exp: exp
    )
  end

  describe '.initialize' do
    it 'ignores :exp_minutes_from_now if :exp set' do
      expires = described_class.new(exp: exp, exp_minutes_from_now: '1').exp
      expect(expires).to eq(exp)
    end

    it 'sets exp if :exp not set, but :exp_minutes_from_now is' do
      Timecop.freeze do
        expires = described_class.new(exp_minutes_from_now: '13').exp
        expect(expires).to eq(Time.now + 13.minutes)
      end
    end
  end

  describe '.parse_auth_header' do
    let(:valid_auth_header) do
      jwt = valid_jwt_payload.to_jwt(private_key: private_key,
                                     algorithm: algorithm)
      "Bearer #{jwt}"
    end

    it 'returns an AccessToken' do
      token = described_class.parse_auth_header(
        valid_auth_header, public_key: public_key, algorithm: algorithm)
      expect(token).to be_an_instance_of(described_class)
    end

    it 'has data' do
      token = described_class.parse_auth_header(
        valid_auth_header, public_key: public_key, algorithm: algorithm)
      expect(token.data).not_to be_nil
    end

    context 'when expiration time has past' do
      let(:exp) { (Time.now.utc - 2.days).beginning_of_day }

      it 'fails with InvalidTokenError' do
        expect do
          described_class.parse_auth_header(
            valid_auth_header, public_key: public_key, algorithm: algorithm)
        end.to raise_error(Shore::Client::Tokens::InvalidTokenError)
      end
    end

    context 'when header is blank' do
      it 'fails with InvalidTokenError' do
        expect do
          described_class.parse_auth_header(
            '', public_key: public_key, algorithm: algorithm)
        end.to raise_error(Shore::Client::Tokens::InvalidTokenError)
      end
    end

    context 'when header is not a valid jwt' do
      it 'fails with InvalidTokenError' do
        expect do
          described_class.parse_auth_header(
            'Bearer nope', public_key: public_key, algorithm: algorithm)
        end.to raise_error(Shore::Client::Tokens::InvalidTokenError)
      end
    end

    context 'when the public_key is wrong' do
      let(:wrong_public_key) { 'the-wrong-public-key' }
      before { expect(wrong_public_key).to_not eq(public_key) }
      it 'fails with InvalidTokenError' do
        expect do
          described_class.parse_auth_header(
            valid_auth_header,
            public_key: wrong_public_key, algorithm: algorithm)
        end.to raise_error(Shore::Client::Tokens::InvalidTokenError)
      end
    end

    context 'when the algorithm is wrong' do
      let(:algorithm) { 'HS384' }
      let(:wrong_algorithm) { 'the-wrong-secret' }
      before { expect(wrong_algorithm).to_not eq(algorithm) }
      it 'fails with InvalidTokenError' do
        expect do
          described_class.parse_auth_header(
            valid_auth_header,
            public_key: public_key, algorithm: wrong_algorithm)
        end.to raise_error(Shore::Client::Tokens::InvalidTokenError)
      end
    end

    context 'when the public key is not provided' do
      it 'fails with InvalidTokenError' do
        expect do
          described_class.parse_auth_header(
            valid_auth_header, public_key: nil, algorithm: algorithm)
        end.to raise_error(Shore::Client::Tokens::InvalidTokenError)
      end
    end

    context 'when the algorithm is not provided' do
      it 'fails with InvalidTokenError' do
        expect do
          described_class.parse_auth_header(
            valid_auth_header, public_key: public_key, algorithm: nil)
        end.to raise_error(Shore::Client::Tokens::InvalidTokenError)
      end
    end
  end

  describe '#to_jwt' do
    context 'without exp' do
      subject(:jwt) do
        described_class.new(data: merchant_token)
          .to_jwt(private_key: private_key, algorithm: algorithm)
      end

      it 'creates jwt' do
        expect(jwt.split('.').size).to eq(3)<commit_msg>C [#COR-1106] Raise an error if the algorithm is not supported by ruby-jwt<commit_after>RSpec.describe Shore::Client::Tokens::AccessToken do
  let(:exp) { (Time.now.utc + 2.days).beginning_of_day }
  let(:algorithm) { 'HS256' }
  let(:public_key) { 'secret' }
  let(:private_key) { 'secret' }
  let(:member) { member_merchant }
  let(:merchant_token) do
    merchant_account_token(SecureRandom.uuid, [member])
  end
  let(:valid_jwt_payload) do
    described_class.new(
      data: merchant_token,
      exp: exp
    )
  end

  describe '.initialize' do
    it 'ignores :exp_minutes_from_now if :exp set' do
      expires = described_class.new(exp: exp, exp_minutes_from_now: '1').exp
      expect(expires).to eq(exp)
    end

    it 'sets exp if :exp not set, but :exp_minutes_from_now is' do
      Timecop.freeze do
        expires = described_class.new(exp_minutes_from_now: '13').exp
        expect(expires).to eq(Time.now + 13.minutes)
      end
    end
  end

  describe '.parse_auth_header' do
    let(:valid_auth_header) do
      jwt = valid_jwt_payload.to_jwt(private_key: private_key,
                                     algorithm: algorithm)
      "Bearer #{jwt}"
    end

    it 'returns an AccessToken' do
      token = described_class.parse_auth_header(
        valid_auth_header, public_key: public_key, algorithm: algorithm)
      expect(token).to be_an_instance_of(described_class)
    end

    it 'has data' do
      token = described_class.parse_auth_header(
        valid_auth_header, public_key: public_key, algorithm: algorithm)
      expect(token.data).not_to be_nil
    end

    context 'when expiration time has past' do
      let(:exp) { (Time.now.utc - 2.days).beginning_of_day }

      it 'fails with InvalidTokenError' do
        expect do
          described_class.parse_auth_header(
            valid_auth_header, public_key: public_key, algorithm: algorithm)
        end.to raise_error(Shore::Client::Tokens::InvalidTokenError)
      end
    end

    context 'when header is blank' do
      it 'fails with InvalidTokenError' do
        expect do
          described_class.parse_auth_header(
            '', public_key: public_key, algorithm: algorithm)
        end.to raise_error(Shore::Client::Tokens::InvalidTokenError)
      end
    end

    context 'when header is not a valid jwt' do
      it 'fails with InvalidTokenError' do
        expect do
          described_class.parse_auth_header(
            'Bearer nope', public_key: public_key, algorithm: algorithm)
        end.to raise_error(Shore::Client::Tokens::InvalidTokenError)
      end
    end

    context 'when the public_key is wrong' do
      let(:wrong_public_key) { 'the-wrong-public-key' }
      before { expect(wrong_public_key).to_not eq(public_key) }
      it 'fails with InvalidTokenError' do
        expect do
          described_class.parse_auth_header(
            valid_auth_header,
            public_key: wrong_public_key, algorithm: algorithm)
        end.to raise_error(Shore::Client::Tokens::InvalidTokenError)
      end
    end

    context 'when the algorithm is wrong' do
      let(:algorithm) { 'HS384' }
      let(:wrong_algorithm) { 'the-wrong-secret' }
      before { expect(wrong_algorithm).to_not eq(algorithm) }
      it 'fails with InvalidTokenError' do
        expect do
          described_class.parse_auth_header(
            valid_auth_header,
            public_key: public_key, algorithm: wrong_algorithm)
        end.to raise_error(Shore::Client::Tokens::InvalidTokenError)
      end
    end

    context 'when the public key is not provided' do
      it 'fails with InvalidTokenError' do
        expect do
          described_class.parse_auth_header(
            valid_auth_header, public_key: nil, algorithm: algorithm)
        end.to raise_error(Shore::Client::Tokens::InvalidTokenError)
      end
    end

    context 'when the algorithm is not provided' do
      it 'fails with InvalidTokenError' do
        expect do
          described_class.parse_auth_header(
            valid_auth_header, public_key: public_key, algorithm: nil)
        end.to raise_error(Shore::Client::Tokens::InvalidTokenError)
      end
    end

    context 'when the algorithm is invalid' do
      it 'fails with InvalidTokenError' do
        expect do
          described_class.parse_auth_header(
            valid_auth_header, public_key: public_key, algorithm: 'invalid-alg')
        end.to raise_error(Shore::Client::Tokens::InvalidTokenError)
      end
    end
  end

  describe '#to_jwt' do
    context 'without exp' do
      subject(:jwt) do
        described_class.new(data: merchant_token)
          .to_jwt(private_key: private_key, algorithm: algorithm)
      end

      it 'creates jwt' do
        expect(jwt.split('.').size).to eq(3)
{'fraction_non_alphanumeric': 0.0873372003940024, 'fraction_numerical': 0.003502243624822152, 'mean_word_length': 2.7869871529216743, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4033668', 'n_tokens_mistral': 2842, 'n_tokens_neox': 2771, 'n_words': 673}