// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef COBALT_DOM_TESTING_FAKE_EXCEPTION_STATE_H_
#define COBALT_DOM_TESTING_FAKE_EXCEPTION_STATE_H_

#include "cobalt/script/exception_state.h"

#include "base/memory/ref_counted.h"
#include "cobalt/dom/dom_exception.h"

namespace cobalt {
namespace dom {
namespace testing {

class FakeExceptionState : public script::ExceptionState {
 public:
  void SetException(
      const scoped_refptr<script::ScriptException>& exception) override {
    dom_exception_ = make_scoped_refptr(
        base::polymorphic_downcast<dom::DOMException*>(exception.get()));
  }
  void SetSimpleExceptionVA(script::SimpleExceptionType /*type*/,
                            const char* /*format*/, va_list /*args*/) override {
    // no-op
  }
  dom::DOMException::ExceptionCode GetExceptionCode() {
    return dom_exception_ ? static_cast<dom::DOMException::ExceptionCode>(
                                dom_exception_->code())
                          : dom::DOMException::kNone;
  }

 private:
  scoped_refptr<dom::DOMException> dom_exception_;
};

}  // namespace testing
}  // namespace dom
}  // namespace cobalt

#endif  // COBALT_DOM_TESTING_FAKE_EXCEPTION_STATE_H_
