diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c
index 93d134ac0c6..59b77a77791 100644
--- a/dlls/mshtml/tests/dom.c
+++ b/dlls/mshtml/tests/dom.c
@@ -33,12 +33,125 @@ static const char doc_blank[] = "";
static const char doc_str1[] = "
test";
static const char doc_str2[] =
"test abc 123
it's text
";
+static const char doc_str3[] =
+ "test"
+ "link"
+ ""
+ ""
+ "";
static const WCHAR noneW[] = {'N','o','n','e',0};
static WCHAR characterW[] = {'c','h','a','r','a','c','t','e','r',0};
static WCHAR wordW[] = {'w','o','r','d',0};
+typedef enum {
+ ET_NONE,
+ ET_HTML,
+ ET_HEAD,
+ ET_TITLE,
+ ET_BODY,
+ ET_A,
+ ET_INPUT,
+ ET_SELECT,
+ ET_TEXTAREA,
+ ET_OPTION
+} elem_type_t;
+
+static const REFIID none_iids[] = {
+ &IID_IUnknown,
+ NULL
+};
+
+static const REFIID html_iids[] = {
+ &IID_IHTMLDOMNode,
+ &IID_IHTMLElement,
+ &IID_IHTMLElement2,
+ NULL
+};
+
+static const REFIID head_iids[] = {
+ &IID_IHTMLDOMNode,
+ &IID_IHTMLElement,
+ &IID_IHTMLElement2,
+ NULL
+};
+
+static const REFIID title_iids[] = {
+ &IID_IHTMLDOMNode,
+ &IID_IHTMLElement,
+ &IID_IHTMLElement2,
+ NULL
+};
+
+static const REFIID body_iids[] = {
+ &IID_IHTMLDOMNode,
+ &IID_IHTMLElement,
+ &IID_IHTMLElement2,
+ &IID_IHTMLTextContainer,
+ &IID_IHTMLBodyElement,
+ NULL
+};
+
+static const REFIID anchor_iids[] = {
+ &IID_IHTMLDOMNode,
+ &IID_IHTMLElement,
+ &IID_IHTMLElement2,
+ &IID_IHTMLAnchorElement,
+ NULL
+};
+
+static const REFIID input_iids[] = {
+ &IID_IHTMLDOMNode,
+ &IID_IHTMLElement,
+ &IID_IHTMLElement2,
+ &IID_IHTMLInputElement,
+ &IID_IHTMLInputTextElement,
+ NULL
+};
+
+static const REFIID select_iids[] = {
+ &IID_IHTMLDOMNode,
+ &IID_IHTMLElement,
+ &IID_IHTMLElement2,
+ &IID_IHTMLSelectElement,
+ NULL
+};
+
+static const REFIID textarea_iids[] = {
+ &IID_IHTMLDOMNode,
+ &IID_IHTMLElement,
+ &IID_IHTMLElement2,
+ &IID_IHTMLTextAreaElement,
+ NULL
+};
+
+static const REFIID option_iids[] = {
+ &IID_IHTMLDOMNode,
+ &IID_IHTMLElement,
+ &IID_IHTMLElement2,
+ &IID_IHTMLOptionElement,
+ NULL
+};
+
+typedef struct {
+ const char *tag;
+ REFIID *iids;
+} elem_type_info_t;
+
+static const elem_type_info_t elem_type_infos[] = {
+ {"", none_iids},
+ {"HTML", html_iids},
+ {"HEAD", head_iids},
+ {"TITLE", title_iids},
+ {"BODY", body_iids},
+ {"A", anchor_iids},
+ {"INPUT", input_iids},
+ {"SELECT", select_iids},
+ {"TEXTAREA", textarea_iids},
+ {"OPTION", option_iids}
+};
+
static const char *dbgstr_w(LPCWSTR str)
{
static char buf[512];
@@ -48,6 +161,18 @@ static const char *dbgstr_w(LPCWSTR str)
return buf;
}
+static const char *dbgstr_guid(REFIID riid)
+{
+ static char buf[50];
+
+ sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+ riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
+ riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
+ riid->Data4[5], riid->Data4[6], riid->Data4[7]);
+
+ return buf;
+}
+
static int strcmp_wa(LPCWSTR strw, const char *stra)
{
WCHAR buf[512];
@@ -55,6 +180,18 @@ static int strcmp_wa(LPCWSTR strw, const char *stra)
return lstrcmpW(strw, buf);
}
+static BSTR a2bstr(const char *str)
+{
+ BSTR ret;
+ int len;
+
+ len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
+ ret = SysAllocStringLen(NULL, len);
+ MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
+
+ return ret;
+}
+
static IHTMLDocument2 *create_document(void)
{
IHTMLDocument2 *doc;
@@ -67,6 +204,21 @@ static IHTMLDocument2 *create_document(void)
return doc;
}
+#define test_ifaces(i,ids) _test_ifaces(__LINE__,i,ids)
+static void _test_ifaces(unsigned line, IUnknown *iface, REFIID *iids)
+{
+ const IID * const *piid;
+ IUnknown *unk;
+ HRESULT hres;
+
+ for(piid = iids; *piid; piid++) {
+ hres = IDispatch_QueryInterface(iface, *piid, (void**)&unk);
+ ok_(__FILE__,line) (hres == S_OK, "Could not get %s interface: %08x\n", dbgstr_guid(*piid), hres);
+ if(SUCCEEDED(hres))
+ IUnknown_Release(unk);
+ }
+}
+
#define test_node_name(u,n) _test_node_name(__LINE__,u,n)
static void _test_node_name(unsigned line, IUnknown *unk, const char *exname)
{
@@ -103,6 +255,13 @@ static void _test_elem_tag(unsigned line, IUnknown *unk, const char *extag)
SysFreeString(tag);
}
+#define test_elem_type(ifc,t) _test_elem_type(__LINE__,ifc,t)
+static void _test_elem_type(unsigned line, IUnknown *unk, elem_type_t type)
+{
+ _test_elem_tag(line, unk, elem_type_infos[type].tag);
+ _test_ifaces(line, unk, elem_type_infos[type].iids);
+}
+
static void test_doc_elem(IHTMLDocument2 *doc)
{
IHTMLElement *elem;
@@ -122,6 +281,142 @@ static void test_doc_elem(IHTMLDocument2 *doc)
IHTMLElement_Release(elem);
}
+#define get_doc_elem(d) _get_doc_elem(__LINE__,d)
+static IHTMLElement *_get_doc_elem(unsigned line, IHTMLDocument2 *doc)
+{
+ IHTMLElement *elem;
+ IHTMLDocument3 *doc3;
+ HRESULT hres;
+
+ hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3);
+ ok_(__FILE__,line) (hres == S_OK, "Could not get IHTMLDocument3 interface: %08x\n", hres);
+ hres = IHTMLDocument3_get_documentElement(doc3, &elem);
+ ok_(__FILE__,line) (hres == S_OK, "get_documentElement failed: %08x\n", hres);
+ IHTMLDocument3_Release(doc3);
+
+ return elem;
+}
+
+#define test_option_text(o,t) _test_option_text(__LINE__,o,t)
+static void _test_option_text(unsigned line, IHTMLOptionElement *option, const char *text)
+{
+ BSTR bstr;
+ HRESULT hres;
+
+ hres = IHTMLOptionElement_get_text(option, &bstr);
+ ok_(__FILE__,line) (hres == S_OK, "get_text failed: %08x\n", hres);
+ ok_(__FILE__,line) (!strcmp_wa(bstr, text), "text=%s\n", dbgstr_w(bstr));
+ SysFreeString(bstr);
+}
+
+#define test_option_put_text(o,t) _test_option_put_text(__LINE__,o,t)
+static void _test_option_put_text(unsigned line, IHTMLOptionElement *option, const char *text)
+{
+ BSTR bstr;
+ HRESULT hres;
+
+ bstr = a2bstr(text);
+ hres = IHTMLOptionElement_put_text(option, bstr);
+ SysFreeString(bstr);
+ ok(hres == S_OK, "put_text failed: %08x\n", hres);
+
+ _test_option_text(line, option, text);
+}
+
+#define test_option_value(o,t) _test_option_value(__LINE__,o,t)
+static void _test_option_value(unsigned line, IHTMLOptionElement *option, const char *value)
+{
+ BSTR bstr;
+ HRESULT hres;
+
+ hres = IHTMLOptionElement_get_value(option, &bstr);
+ ok_(__FILE__,line) (hres == S_OK, "get_value failed: %08x\n", hres);
+ ok_(__FILE__,line) (!strcmp_wa(bstr, value), "value=%s\n", dbgstr_w(bstr));
+ SysFreeString(bstr);
+}
+
+#define test_option_put_value(o,t) _test_option_put_value(__LINE__,o,t)
+static void _test_option_put_value(unsigned line, IHTMLOptionElement *option, const char *value)
+{
+ BSTR bstr;
+ HRESULT hres;
+
+ bstr = a2bstr(value);
+ hres = IHTMLOptionElement_put_value(option, bstr);
+ SysFreeString(bstr);
+ ok(hres == S_OK, "put_value failed: %08x\n", hres);
+
+ _test_option_value(line, option, value);
+}
+
+#define create_option_elem(d,t,v) _create_option_elem(__LINE__,d,t,v)
+static IHTMLOptionElement *_create_option_elem(unsigned line, IHTMLDocument2 *doc,
+ const char *txt, const char *val)
+{
+ IHTMLOptionElementFactory *factory;
+ IHTMLOptionElement *option;
+ IHTMLWindow2 *window;
+ VARIANT text, value, empty;
+ HRESULT hres;
+
+ hres = IHTMLDocument2_get_parentWindow(doc, &window);
+ ok_(__FILE__,line) (hres == S_OK, "get_parentElement failed: %08x\n", hres);
+
+ hres = IHTMLWindow2_get_Option(window, &factory);
+ IHTMLWindow2_Release(window);
+ ok_(__FILE__,line) (hres == S_OK, "get_Option failed: %08x\n", hres);
+
+ V_VT(&text) = VT_BSTR;
+ V_BSTR(&text) = a2bstr(txt);
+ V_VT(&value) = VT_BSTR;
+ V_BSTR(&value) = a2bstr(val);
+ V_VT(&empty) = VT_EMPTY;
+
+ hres = IHTMLOptionElementFactory_create(factory, text, value, empty, empty, &option);
+ ok_(__FILE__,line) (hres == S_OK, "create failed: %08x\n", hres);
+
+ IHTMLOptionElementFactory_Release(factory);
+ VariantClear(&text);
+ VariantClear(&value);
+
+ _test_option_text(line, option, txt);
+ _test_option_value(line, option, val);
+
+ return option;
+}
+
+#define test_select_length(s,l) _test_select_length(__LINE__,s,l)
+static void _test_select_length(unsigned line, IHTMLSelectElement *select, long length)
+{
+ long len = 0xdeadbeef;
+ HRESULT hres;
+
+ hres = IHTMLSelectElement_get_length(select, &len);
+ ok_(__FILE__,line) (hres == S_OK, "get_length failed: %08x\n", hres);
+ ok_(__FILE__,line) (len == length, "len=%ld, expected %ld\n", len, length);
+}
+
+#define test_select_selidx(s,i) _test_select_selidx(__LINE__,s,i)
+static void _test_select_selidx(unsigned line, IHTMLSelectElement *select, long index)
+{
+ long idx = 0xdeadbeef;
+ HRESULT hres;
+
+ hres = IHTMLSelectElement_get_selectedIndex(select, &idx);
+ ok_(__FILE__,line) (hres == S_OK, "get_selectedIndex failed: %08x\n", hres);
+ ok_(__FILE__,line) (idx == index, "idx=%ld, expected %ld\n", idx, index);
+}
+
+#define test_select_put_selidx(s,i) _test_select_put_selidx(__LINE__,s,i)
+static void _test_select_put_selidx(unsigned line, IHTMLSelectElement *select, long index)
+{
+ HRESULT hres;
+
+ hres = IHTMLSelectElement_put_selectedIndex(select, index);
+ ok_(__FILE__,line) (hres == S_OK, "get_selectedIndex failed: %08x\n", hres);
+ _test_select_selidx(line, select, index);
+}
+
#define test_range_text(r,t) _test_range_text(__LINE__,r,t)
static void _test_range_text(unsigned line, IHTMLTxtRange *range, const char *extext)
{
@@ -232,6 +527,157 @@ static void _test_range_isequal(unsigned line, IHTMLTxtRange *range1, IHTMLTxtRa
}
}
+static void test_elem_collection(IHTMLElementCollection *col, const elem_type_t *elem_types, long exlen)
+{
+ long len;
+ DWORD i;
+ VARIANT name, index;
+ IDispatch *disp;
+ HRESULT hres;
+
+ hres = IHTMLElementCollection_get_length(col, &len);
+ ok(hres == S_OK, "get_length failed: %08x\n", hres);
+ ok(len == exlen, "len=%ld, expected %ld\n", len, exlen);
+
+ V_VT(&index) = VT_EMPTY;
+ V_VT(&name) = VT_I4;
+
+ for(i=0; i