// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "core/dom/custom/CustomElementsRegistry.h"

#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/ScriptValue.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
#include "core/dom/ElementRegistrationOptions.h"
#include "core/dom/custom/CEReactionsScope.h"
#include "core/dom/custom/CustomElementDefinition.h"
#include "core/dom/custom/CustomElementDefinitionBuilder.h"
#include "core/dom/custom/CustomElementDescriptor.h"
#include "core/dom/custom/CustomElementTestHelpers.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/dom/shadow/ShadowRootInit.h"
#include "core/testing/DummyPageHolder.h"
#include "platform/ScriptForbiddenScope.h"
#include "platform/heap/Handle.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "wtf/text/AtomicString.h"
#include <memory>

namespace blink {

class CustomElementsRegistryTestBase : public ::testing::Test {
protected:
    virtual Document& document() = 0;
    virtual CustomElementsRegistry& registry() = 0;

    void collectCandidates(
        const CustomElementDescriptor& desc,
        HeapVector<Member<Element>>* elements)
    {
        registry().collectCandidates(desc, elements);
    }
};

class CustomElementsRegistryTest : public CustomElementsRegistryTestBase {
protected:
    void SetUp() override
    {
        CustomElementsRegistryTestBase::SetUp();

        m_document = HTMLDocument::create();
        m_document->appendChild(CreateElement("html").inDocument(m_document));

        m_registry = CustomElementsRegistry::create(m_document);
    }

    void TearDown() override
    {
        m_document = nullptr;
        m_registry = nullptr;
        CustomElementsRegistryTestBase::TearDown();
    }

    Document& document() override { return *m_document; }
    CustomElementsRegistry& registry() override { return *m_registry; }

private:
    Persistent<Document> m_document;
    Persistent<CustomElementsRegistry> m_registry;
};

class CustomElementsRegistryFrameTest : public CustomElementsRegistryTestBase {
protected:
    void SetUp() override
    {
        CustomElementsRegistryTestBase::SetUp();
        m_page.reset(DummyPageHolder::create(IntSize(1, 1)).release());
    }

    void TearDown() override
    {
        m_page = nullptr;
        CustomElementsRegistryTestBase::TearDown();
    }

    Document& document() override { return m_page->document(); }

    CustomElementsRegistry& registry() override
    {
        return *m_page->frame().localDOMWindow()->customElements();
    }

    ScriptState* scriptState()
    {
        return ScriptState::forMainWorld(&m_page->frame());
    }

    ShadowRoot* attachShadowTo(Element* element)
    {
        NonThrowableExceptionState noExceptions;
        ShadowRootInit shadowRootInit;
        return
            element->attachShadow(scriptState(), shadowRootInit, noExceptions);
    }

private:
    std::unique_ptr<DummyPageHolder> m_page;
};

TEST_F(
    CustomElementsRegistryTest,
    collectCandidates_shouldNotIncludeElementsRemovedFromDocument)
{
    Element* element = CreateElement("a-a").inDocument(&document());
    registry().addCandidate(element);

    HeapVector<Member<Element>> elements;
    collectCandidates(
        CustomElementDescriptor("a-a", "a-a"),
        &elements);

    EXPECT_TRUE(elements.isEmpty())
        << "no candidates should have been found, but we have "
        << elements.size();
    EXPECT_FALSE(elements.contains(element))
        << "the out-of-document candidate should not have been found";
}

TEST_F(
    CustomElementsRegistryTest,
    collectCandidates_shouldNotIncludeElementsInDifferentDocument)
{
    Element* element = CreateElement("a-a").inDocument(&document());
    registry().addCandidate(element);

    Document* otherDocument = HTMLDocument::create();
    otherDocument->appendChild(element);
    EXPECT_EQ(otherDocument, element->ownerDocument())
        << "sanity: another document should have adopted an element on append";

    HeapVector<Member<Element>> elements;
    collectCandidates(
        CustomElementDescriptor("a-a", "a-a"),
        &elements);

    EXPECT_TRUE(elements.isEmpty())
        << "no candidates should have been found, but we have "
        << elements.size();
    EXPECT_FALSE(elements.contains(element))
        << "the adopted-away candidate should not have been found";
}

TEST_F(
    CustomElementsRegistryTest,
    collectCandidates_shouldOnlyIncludeCandidatesMatchingDescriptor)
{
    CustomElementDescriptor descriptor("hello-world", "hello-world");

    // Does not match: namespace is not HTML
    Element* elementA = CreateElement("hello-world")
        .inDocument(&document())
        .inNamespace("data:text/date,1981-03-10");
    // Matches
    Element* elementB = CreateElement("hello-world").inDocument(&document());
    // Does not match: local name is not hello-world
    Element* elementC = CreateElement("button")
        .inDocument(&document())
        .withIsAttribute("hello-world");
    document().documentElement()->appendChild(elementA);
    elementA->appendChild(elementB);
    elementA->appendChild(elementC);

    registry().addCandidate(elementA);
    registry().addCandidate(elementB);
    registry().addCandidate(elementC);

    HeapVector<Member<Element>> elements;
    collectCandidates(descriptor, &elements);

    EXPECT_EQ(1u, elements.size())
        << "only one candidates should have been found";
    EXPECT_EQ(elementB, elements[0])
        << "the matching element should have been found";
}

TEST_F(CustomElementsRegistryTest, collectCandidates_oneCandidate)
{
    Element* element = CreateElement("a-a").inDocument(&document());
    registry().addCandidate(element);
    document().documentElement()->appendChild(element);

    HeapVector<Member<Element>> elements;
    collectCandidates(
        CustomElementDescriptor("a-a", "a-a"),
        &elements);

    EXPECT_EQ(1u, elements.size())
        << "exactly one candidate should have been found";
    EXPECT_TRUE(elements.contains(element))
        << "the candidate should be the element that was added";
}

TEST_F(CustomElementsRegistryTest, collectCandidates_shouldBeInDocumentOrder)
{
    CreateElement factory = CreateElement("a-a");
    factory.inDocument(&document());
    Element* elementA = factory.withId("a");
    Element* elementB = factory.withId("b");
    Element* elementC = factory.withId("c");

    registry().addCandidate(elementB);
    registry().addCandidate(elementA);
    registry().addCandidate(elementC);

    document().documentElement()->appendChild(elementA);
    elementA->appendChild(elementB);
    document().documentElement()->appendChild(elementC);

    HeapVector<Member<Element>> elements;
    collectCandidates(
        CustomElementDescriptor("a-a", "a-a"),
        &elements);

    EXPECT_EQ(elementA, elements[0].get());
    EXPECT_EQ(elementB, elements[1].get());
    EXPECT_EQ(elementC, elements[2].get());
}

class TestCustomElementDefinition : public CustomElementDefinition {
    WTF_MAKE_NONCOPYABLE(TestCustomElementDefinition);
public:
    TestCustomElementDefinition(const CustomElementDescriptor& descriptor)
        : CustomElementDefinition(descriptor)
    {
    }

    TestCustomElementDefinition(const CustomElementDescriptor& descriptor,
        const HashSet<AtomicString>& observedAttributes)
        : CustomElementDefinition(descriptor, observedAttributes)
    {
    }

    ~TestCustomElementDefinition() override = default;

    ScriptValue getConstructorForScript() override
    {
        return ScriptValue();
    }

    bool runConstructor(Element* element) override
    {
        if (constructionStack().isEmpty()
            || constructionStack().last() != element)
            return false;
        constructionStack().last().clear();
        return true;
    }

    HTMLElement* createElementSync(Document&, const QualifiedName&) override
    {
        return nullptr;
    }

    HTMLElement* createElementSync(Document&, const QualifiedName&, ExceptionState&) override
    {
        return nullptr;
    }
};

// Classes which use trace macros cannot be local because of the
// traceImpl template.
class LogUpgradeDefinition : public TestCustomElementDefinition {
    WTF_MAKE_NONCOPYABLE(LogUpgradeDefinition);
public:
    LogUpgradeDefinition(const CustomElementDescriptor& descriptor)
        : TestCustomElementDefinition(descriptor, {
            "attr1",
            "attr2",
            HTMLNames::contenteditableAttr.localName(),
        })
    {
    }

    DEFINE_INLINE_VIRTUAL_TRACE()
    {
        TestCustomElementDefinition::trace(visitor);
        visitor->trace(m_element);
    }

    // TODO(dominicc): Make this class collect a vector of what's
    // upgraded; it will be useful in more tests.
    Member<Element> m_element;
    enum MethodType {
        Constructor,
        ConnectedCallback,
        DisconnectedCallback,
        AttributeChangedCallback,
    };
    Vector<MethodType> m_logs;

    struct AttributeChanged {
        QualifiedName name;
        AtomicString oldValue;
        AtomicString newValue;
    };
    Vector<AttributeChanged> m_attributeChanged;

    void clear()
    {
        m_logs.clear();
        m_attributeChanged.clear();
    }

    bool runConstructor(Element* element) override
    {
        m_logs.append(Constructor);
        m_element = element;
        return TestCustomElementDefinition::runConstructor(element);
    }

    bool hasConnectedCallback() const override { return true; }
    bool hasDisconnectedCallback() const override { return true; }

    void runConnectedCallback(Element* element) override
    {
        m_logs.append(ConnectedCallback);
        EXPECT_EQ(element, m_element);
    }

    void runDisconnectedCallback(Element* element) override
    {
        m_logs.append(DisconnectedCallback);
        EXPECT_EQ(element, m_element);
    }

    void runAttributeChangedCallback(Element* element, const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue) override
    {
        m_logs.append(AttributeChangedCallback);
        EXPECT_EQ(element, m_element);
        m_attributeChanged.append(AttributeChanged { name, oldValue, newValue });
    }
};

class LogUpgradeBuilder final : public CustomElementDefinitionBuilder {
    STACK_ALLOCATED();
    WTF_MAKE_NONCOPYABLE(LogUpgradeBuilder);
public:
    LogUpgradeBuilder() { }

    bool checkConstructorIntrinsics() override { return true; }
    bool checkConstructorNotRegistered() override { return true; }
    bool checkPrototype() override { return true; }
    bool rememberOriginalProperties() override { return true; }
    CustomElementDefinition* build(
        const CustomElementDescriptor& descriptor) {
        return new LogUpgradeDefinition(descriptor);
    }
};

TEST_F(CustomElementsRegistryFrameTest, define_upgradesInDocumentElements)
{
    ScriptForbiddenScope doNotRelyOnScript;

    Element* element = CreateElement("a-a").inDocument(&document());
    element->setAttribute(QualifiedName(nullAtom, "attr1", HTMLNames::xhtmlNamespaceURI), "v1");
    element->setBooleanAttribute(HTMLNames::contenteditableAttr, true);
    document().documentElement()->appendChild(element);

    LogUpgradeBuilder builder;
    NonThrowableExceptionState shouldNotThrow;
    {
        CEReactionsScope reactions;
        registry().define(
            "a-a",
            builder,
            ElementRegistrationOptions(),
            shouldNotThrow);
    }
    LogUpgradeDefinition* definition =
        static_cast<LogUpgradeDefinition*>(registry().definitionForName("a-a"));
    EXPECT_EQ(LogUpgradeDefinition::Constructor, definition->m_logs[0])
        << "defining the element should have 'upgraded' the existing element";
    EXPECT_EQ(element, definition->m_element)
        << "the existing a-a element should have been upgraded";

    EXPECT_EQ(LogUpgradeDefinition::AttributeChangedCallback, definition->m_logs[1])
        << "Upgrade should invoke attributeChangedCallback for all attributes";
    EXPECT_EQ("attr1", definition->m_attributeChanged[0].name);
    EXPECT_EQ(nullAtom, definition->m_attributeChanged[0].oldValue);
    EXPECT_EQ("v1", definition->m_attributeChanged[0].newValue);

    EXPECT_EQ(LogUpgradeDefinition::AttributeChangedCallback, definition->m_logs[2])
        << "Upgrade should invoke attributeChangedCallback for all attributes";
    EXPECT_EQ("contenteditable", definition->m_attributeChanged[1].name);
    EXPECT_EQ(nullAtom, definition->m_attributeChanged[1].oldValue);
    EXPECT_EQ(emptyAtom, definition->m_attributeChanged[1].newValue);
    EXPECT_EQ(2u, definition->m_attributeChanged.size())
        << "Upgrade should invoke attributeChangedCallback for all attributes";

    EXPECT_EQ(LogUpgradeDefinition::ConnectedCallback, definition->m_logs[3])
        << "upgrade should invoke connectedCallback";

    EXPECT_EQ(4u, definition->m_logs.size())
        << "upgrade should not invoke other callbacks";
}

TEST_F(CustomElementsRegistryFrameTest, attributeChangedCallback)
{
    ScriptForbiddenScope doNotRelyOnScript;

    Element* element = CreateElement("a-a").inDocument(&document());
    document().documentElement()->appendChild(element);

    LogUpgradeBuilder builder;
    NonThrowableExceptionState shouldNotThrow;
    {
        CEReactionsScope reactions;
        registry().define(
            "a-a",
            builder,
            ElementRegistrationOptions(),
            shouldNotThrow);
    }
    LogUpgradeDefinition* definition =
        static_cast<LogUpgradeDefinition*>(registry().definitionForName("a-a"));

    definition->clear();
    {
        CEReactionsScope reactions;
        element->setAttribute(QualifiedName(nullAtom, "attr2", HTMLNames::xhtmlNamespaceURI), "v2");
    }
    EXPECT_EQ(LogUpgradeDefinition::AttributeChangedCallback, definition->m_logs[0])
        << "Adding an attribute should invoke attributeChangedCallback";
    EXPECT_EQ(1u, definition->m_attributeChanged.size())
        << "Adding an attribute should invoke attributeChangedCallback";
    EXPECT_EQ("attr2", definition->m_attributeChanged[0].name);
    EXPECT_EQ(nullAtom, definition->m_attributeChanged[0].oldValue);
    EXPECT_EQ("v2", definition->m_attributeChanged[0].newValue);

    EXPECT_EQ(1u, definition->m_logs.size())
        << "upgrade should not invoke other callbacks";
}

TEST_F(CustomElementsRegistryFrameTest, disconnectedCallback)
{
    ScriptForbiddenScope doNotRelyOnScript;

    Element* element = CreateElement("a-a").inDocument(&document());
    document().documentElement()->appendChild(element);

    LogUpgradeBuilder builder;
    NonThrowableExceptionState shouldNotThrow;
    {
        CEReactionsScope reactions;
        registry().define(
            "a-a",
            builder,
            ElementRegistrationOptions(),
            shouldNotThrow);
    }
    LogUpgradeDefinition* definition =
        static_cast<LogUpgradeDefinition*>(registry().definitionForName("a-a"));

    definition->clear();
    {
        CEReactionsScope reactions;
        element->remove(shouldNotThrow);
    }
    EXPECT_EQ(LogUpgradeDefinition::DisconnectedCallback, definition->m_logs[0])
        << "remove() should invoke disconnectedCallback";

    EXPECT_EQ(1u, definition->m_logs.size())
        << "remove() should not invoke other callbacks";
}

// TODO(dominicc): Add tests which adjust the "is" attribute when type
// extensions are implemented.

} // namespace blink
