namespace PlaywrightStudy.Test
{
    public class PlaywrightTest
    {
        /// <summary>
        /// 通过 API 安装浏览器
        /// 当然有多种安装方式
        /// </summary>
        [Fact]
        public void Install_Browsers_Test()
        {
            var exitCode = Microsoft.Playwright.Program.Main(new[] { "install" });
            if (exitCode != 0)
            {
                throw new Exception($"Playwright exited with code {exitCode}");
            }
        }

        #region Edge
        [Fact]
        public async void Baidu_Edge_Test()
        {
            using var playwright = await Playwright.CreateAsync();

            //await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions()
            //{
            //    SlowMo              = 50,           //慢速
            //    Headless            =  false,        // 关闭无头模式(有界面)
            //    Channel             = "msedge",     // 指定采用chrome浏览器类型()
            //    Devtools            = false,         // 启用开发者工具
            //    ChromiumSandbox     = false,        // 关闭浏览器沙盒
            //    ExecutablePath      = string.Empty, // 不指定浏览器可执行文件位置,会自动寻找 ms-playwright 下载的浏览器
            //    Args = new[] { "--enable-automation=true", "--disable-blink-features=AutomationControlled" }, // 防止selenium被检测
            //});

            //浏览器:默认Edge优先
            await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions() 
            {
                //关闭无头模式(有界面)
                Headless = false,
            });

            //浏览器上下文
            var browserContexts = browser.Contexts;

            //页面
            var page = await browser.NewPageAsync();

            //页面响应
            var response = await page.GotoAsync("https://www.baidu.com/");

            //定位器:搜索框
            var searchBoxLocator = page.GetByRole(AriaRole.Textbox).Nth(0);

            //元素个数
            var count = await searchBoxLocator.CountAsync();

            //xUnit断言
            Assert.True(count > 0);

            //Playwright断言
            await Microsoft.Playwright.Assertions.Expect(searchBoxLocator).ToHaveCountAsync(1);

            //输入搜索内容前部分(一次性全部输入)
            await searchBoxLocator.FillAsync("Playwright");

            //输入搜索内容后部分(模拟用户输入:每个字符之间有延时),已弃用
            //await textboxLocator.TypeAsync(".net", new LocatorTypeOptions { Delay = 1000 });

            //输入搜索内容后部分(模拟用户输入:每个字符之间有延时)
            await searchBoxLocator.PressSequentiallyAsync(".NET", new LocatorPressSequentiallyOptions { Delay = 200 });

            //输入回车:确认搜索[可输入特殊字符,也可以是组合键("Shift+Home"、"Alt+Enter")]
            //await searchBoxLocator.PressAsync("Enter");

            //方法二:单击搜索按钮
            var searchButtonLocator = page.Locator("#su");

            var searchButtonCount = await searchButtonLocator.CountAsync();

            //断言:按钮找到
            await Microsoft.Playwright.Assertions.Expect(searchButtonLocator).ToHaveCountAsync(1);

            //单击搜索按钮
            await searchButtonLocator.ClickAsync();

            //使用 page.Keyboard 和 page.Mouse 对象来模拟键盘和鼠标的操作
            //await page.Keyboard.PressAsync("Enter");
            //await page.Mouse.ClickAsync(100, 100);

            await page.WaitForLoadStateAsync();

            //页面截图
            await page.ScreenshotAsync(new()
            {
                Path = "Baidu.Edge.Screenshot.png",
                FullPage = true, //整页截图
            });

            //元素截图
            var paggerLocator = page.Locator("#page");

            //无此行,则元素截图错误
            var paagerCount = await paggerLocator.CountAsync();

            await paggerLocator.ScreenshotAsync(new LocatorScreenshotOptions() 
            {
                Path = "Baidu.Edge.ByPage.Screenshot.png",
                //Quality = 100,
                Type = ScreenshotType.Png
            });

            //网页保存为Pdf文件
            await page.PdfAsync(new()
            {
                Path = "Baidu.Edge.pdf",
                DisplayHeaderFooter = false,
                Format = "A4"
            });
        }

        [Fact]
        public async void Bing_Edge_Test()
        {
            using var playwright = await Playwright.CreateAsync();

            //浏览器:默认Edge优先
            await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions()
            {
                //关闭无头模式(有界面)
                Headless = false,
            });

            //浏览器上下文
            var browserContexts = browser.Contexts;

            //页面
            var page = await browser.NewPageAsync();

            //页面响应
            var response = await page.GotoAsync("https://cn.bing.com/");

            //请求成功
            Assert.Equal(200, response?.Status);

            //定位器:搜索框
            var searchBoxLocator = page.Locator("input#sb_form_q");

            //输入框个数
            var count = await searchBoxLocator.CountAsync();

            //xUnit断言
            Assert.True(count > 0);

            //Playwright断言
            await Microsoft.Playwright.Assertions.Expect(searchBoxLocator).ToHaveCountAsync(1);

            //输入搜索内容前部分(一次性全部输入)
            //await searchBoxLocator.FillAsync("Playwright");

            //输入搜索内容后部分(模拟用户输入:每个字符之间有延时)
            await searchBoxLocator.PressSequentiallyAsync("Playwright.NET", new LocatorPressSequentiallyOptions { Delay = 200 });

            //输入回车:确认搜索[可输入特殊字符,也可以是组合键("Shift+Home"、"Alt+Enter")]
            await searchBoxLocator.PressAsync("Enter");

            await page.WaitForLoadStateAsync();

            //截图
            await page.ScreenshotAsync(new()
            {
                Path = "Bing.Edge.Screenshot.png"
            });

            //网页保存为Pdf文件
            await page.PdfAsync(new()
            {
                Path = "Bing.Edge.pdf",
                DisplayHeaderFooter = false,
                Format = "A4"
            });
        }

        #endregion

        #region Chrome

        /// <summary>
        /// 比较详细
        /// </summary>
        [Fact]
        public async void Baidu_Chrome_Test()
        {
            using var playwright = await Playwright.CreateAsync();

            //浏览器:指定 chrome
            await using var browser = await playwright.Chromium.LaunchAsync(new BrowserTypeLaunchOptions()
            {
                SlowMo              = 50,           //慢速
                Headless            = false,        // 关闭无头模式(有界面)
                Channel             = "chrome",     // 指定采用chrome浏览器类型()
                Devtools            = false,         // 启用开发者工具
                ChromiumSandbox     = true,        // 关闭浏览器沙盒
                ExecutablePath      = string.Empty, // 不指定浏览器可执行文件位置,会自动寻找 ms-playwright 下载的浏览器
                DownloadsPath       = "download",
            });

            //页面
            var page = await browser.NewPageAsync();

            //页面响应
            var response = await page.GotoAsync("https://www.baidu.com/");

            //定位器:搜索框
            var searchBoxLocator = page.GetByRole(AriaRole.Textbox).Nth(0);

            //元素个数
            var count = await searchBoxLocator.CountAsync();

            //xUnit断言
            Assert.True(count > 0);

            //Playwright断言
            await Microsoft.Playwright.Assertions.Expect(searchBoxLocator).ToHaveCountAsync(1);

            //输入搜索内容前部分(一次性全部输入)
            //await searchBoxLocator.FillAsync("Playwright");

            //输入搜索内容后部分(模拟用户输入:每个字符之间有延时)
            await searchBoxLocator.PressSequentiallyAsync("Playwright.NET", new LocatorPressSequentiallyOptions { Delay = 200 });

            //输入回车:确认搜索[可输入特殊字符,也可以是组合键("Shift+Home"、"Alt+Enter")]
            await searchBoxLocator.PressAsync("Enter");

            //等待
            await page.WaitForLoadStateAsync(LoadState.DOMContentLoaded);

            //截图
            await page.ScreenshotAsync(new()
            {
                Path = "Baidu.Chrome.Screenshot.png"
            });

            //网页保存为Pdf文件
            await page.PdfAsync(new()
            {
                Path = "Baidu.Chrome.pdf",
                DisplayHeaderFooter = false,
                Format = "A4"
            });
        }

        
        #endregion

        #region Firefox
        [Fact]
        public async void Baidu_Firefox_Test()
        {
            using var playwright = await Playwright.CreateAsync();

            //浏览器:指定 chrome
            await using var browser = await playwright.Firefox.LaunchAsync(new BrowserTypeLaunchOptions()
            {
                SlowMo = 50,           //慢速
                Headless = false,        // 关闭无头模式(有界面
                Devtools = false,         // 启用开发者工具
                ChromiumSandbox = true,        // 关闭浏览器沙盒
                ExecutablePath = string.Empty, // 不指定浏览器可执行文件位置,会自动寻找 ms-playwright 下载的浏览器
                DownloadsPath = "download",
            });

            //页面
            var page = await browser.NewPageAsync();

            //页面响应
            var response = await page.GotoAsync("https://www.baidu.com/");

            //定位器:搜索框
            var searchBoxLocator = page.GetByRole(AriaRole.Textbox).Nth(0);

            //元素个数
            var count = await searchBoxLocator.CountAsync();

            //xUnit断言
            Assert.True(count > 0);

            //Playwright断言
            await Microsoft.Playwright.Assertions.Expect(searchBoxLocator).ToHaveCountAsync(1);

            //输入搜索内容前部分(一次性全部输入)
            //await searchBoxLocator.FillAsync("Playwright");

            //输入搜索内容后部分(模拟用户输入:每个字符之间有延时)
            await searchBoxLocator.PressSequentiallyAsync("Playwright.NET", new LocatorPressSequentiallyOptions { Delay = 200 });

            //输入回车:确认搜索[可输入特殊字符,也可以是组合键("Shift+Home"、"Alt+Enter")]
            await searchBoxLocator.PressAsync("Enter");

            //等待
            await page.WaitForLoadStateAsync(LoadState.DOMContentLoaded);

            //截图
            await page.ScreenshotAsync(new()
            {
                Path = "Baidu.Firefox.Screenshot.png"
            });

            //网页保存为Pdf文件:FireFox不支持
            //await page.PdfAsync(new()
            //{
            //    Path = "Baidu.Firefox.pdf",
            //    DisplayHeaderFooter = false,
            //    Format = "A4"
            //});
        }

        [Fact]
        public async void Bing_Firefox_Test()
        {
            using var playwright = await Playwright.CreateAsync();

            //浏览器:指定 chrome
            await using var browser = await playwright.Firefox.LaunchAsync(new BrowserTypeLaunchOptions()
            {
                SlowMo = 50,           //慢速
                Headless = false,        // 关闭无头模式(有界面
                Devtools = false,         // 启用开发者工具
                ChromiumSandbox = true,        // 关闭浏览器沙盒
                ExecutablePath = string.Empty, // 不指定浏览器可执行文件位置,会自动寻找 ms-playwright 下载的浏览器
                DownloadsPath = "download",
            });

            //浏览器上下文
            var browserContexts = browser.Contexts;

            //页面
            var page = await browser.NewPageAsync();

            //页面响应
            var response = await page.GotoAsync("https://cn.bing.com/");

            //请求成功
            Assert.Equal(200, response?.Status);

            //定位器:搜索框
            var searchBoxLocator = page.Locator("input#sb_form_q");

            //输入框个数
            var count = await searchBoxLocator.CountAsync();

            //xUnit断言
            Assert.True(count > 0);

            //Playwright断言
            await Microsoft.Playwright.Assertions.Expect(searchBoxLocator).ToHaveCountAsync(1);

            //输入搜索内容前部分(一次性全部输入)
            //await searchBoxLocator.FillAsync("Playwright");

            //输入搜索内容后部分(模拟用户输入:每个字符之间有延时)
            await searchBoxLocator.PressSequentiallyAsync("Playwright.NET", new LocatorPressSequentiallyOptions { Delay = 200 });

            //输入回车:确认搜索[可输入特殊字符,也可以是组合键("Shift+Home"、"Alt+Enter")]
            await searchBoxLocator.PressAsync("Enter");

            await page.WaitForLoadStateAsync();

            //截图
            await page.ScreenshotAsync(new()
            {
                Path = "Bing.Firefox.Screenshot.png"
            });

            //网页保存为Pdf文件
            //await page.PdfAsync(new()
            //{
            //    Path = "Bing.Firefox.pdf",
            //    DisplayHeaderFooter = false,
            //    Format = "A4"
            //});
        }
        #endregion

        #region WebKit
        [Fact]
        public async void Baidu_WebKit_Test()
        {
            using var playwright = await Playwright.CreateAsync();

            //浏览器:指定 chrome
            await using var browser = await playwright.Webkit.LaunchAsync(new BrowserTypeLaunchOptions()
            {
                SlowMo              = 50,               //慢速
                Headless            = false,            // 关闭无头模式(有界面
                Devtools            = false,            // 启用开发者工具
                ChromiumSandbox     = true,             // 关闭浏览器沙盒
                ExecutablePath      = string.Empty,     // 不指定浏览器可执行文件位置,会自动寻找 ms-playwright 下载的浏览器
                DownloadsPath       = "download",
            });

            //页面
            var page = await browser.NewPageAsync();

            //页面响应
            var response = await page.GotoAsync("https://www.baidu.com/");

            //定位器:搜索框
            var searchBoxLocator = page.GetByRole(AriaRole.Textbox).Nth(0);

            //元素个数
            var count = await searchBoxLocator.CountAsync();

            //xUnit断言
            Assert.True(count > 0);

            //Playwright断言
            await Microsoft.Playwright.Assertions.Expect(searchBoxLocator).ToHaveCountAsync(1);

            //输入搜索内容前部分(一次性全部输入)
            //await searchBoxLocator.FillAsync("Playwright");

            //输入搜索内容后部分(模拟用户输入:每个字符之间有延时)
            await searchBoxLocator.PressSequentiallyAsync("Playwright.NET", new LocatorPressSequentiallyOptions { Delay = 200 });

            //输入回车:确认搜索[可输入特殊字符,也可以是组合键("Shift+Home"、"Alt+Enter")]
            await searchBoxLocator.PressAsync("Enter");

            //等待
            await page.WaitForLoadStateAsync(LoadState.DOMContentLoaded);

            //截图
            await page.ScreenshotAsync(new()
            {
                Path = "Baidu.WebKit.Screenshot.png"
            });

            //网页保存为Pdf文件:FireFox不支持
            //await page.PdfAsync(new()
            //{
            //    Path = "Baidu.WebKit.pdf",
            //    DisplayHeaderFooter = false,
            //    Format = "A4"
            //});
        }
        #endregion

        #region WebAPI
        /// <summary>
        ///  使用免费接口
        /// </summary>
        [Fact]
        public async Task WebAPI_TestAsync()
        {
            //https://docs.tenapi.cn/ 免费接口
            //IP查询 https://tenapi.cn/v2/getip?ip=192.168.1.1

            using var playwright = await Playwright.CreateAsync();
            var apiRequestContext = await playwright.APIRequest.NewContextAsync(new APIRequestNewContextOptions() 
            {
                BaseURL="https://tenapi.cn",
                ExtraHTTPHeaders = new Dictionary<string, string>()
                {
                    { "Accept","text/html"},

                     //全局认证
                    { "Authorization","Bear a.b.c"}
                },
                //HttpCredentials = new HttpCredentials() { Origin="http://localhost:8060",Username="admin",Password="123456" },
                //IgnoreHTTPSErrors = true,   //设置代理时,忽略证书错误
                Timeout = 30*1000,
            });

            var apiResponse = await apiRequestContext.GetAsync("v2/getip?ip=192.168.1.1");

            Assert.True(apiResponse.Ok);

            var ipResult = await apiResponse.JsonAsync<TenApiReturnBase<GetIP>>();

            Assert.NotNull(ipResult);
            Assert.IsType<TenApiReturnBase<GetIP>>(ipResult);

            Assert.Equal("获取成功", ipResult.msg);
           
        }

        /// <summary>
        ///  使用Fiddler抓包:设置Fiddler为代理服务器,必须先启动Fiddler
        /// </summary>
        [Fact]
        public async Task WebAPI_FiddleProxy_TestAsync()
        {
            //https://docs.tenapi.cn/ 免费接口
            //IP查询 https://tenapi.cn/v2/getip?ip=192.168.1.1

            using var playwright = await Playwright.CreateAsync();
            var apiRequestContext = await playwright.APIRequest.NewContextAsync(new APIRequestNewContextOptions()
            {
                BaseURL = "https://tenapi.cn",
                ExtraHTTPHeaders = new Dictionary<string, string>()
                {
                    { "Accept","text/html"},
                    { "Authorization","Bear a.b.c"}
                },
                IgnoreHTTPSErrors = true,   //设置代理时,忽略证书错误
                Timeout = 30 * 1000,
                Proxy = new Proxy() { Server = "http://127.0.0.1:8888" }
            });

            var apiResponse = await apiRequestContext.GetAsync("v2/getip?ip=192.168.1.1");

            Assert.True(apiResponse.Ok);

            var ipResult = await apiResponse.JsonAsync<TenApiReturnBase<GetIP>>();

            Assert.NotNull(ipResult);
            Assert.IsType<TenApiReturnBase<GetIP>>(ipResult);

            Assert.Equal("获取成功", ipResult.msg);

        }
        #endregion
    }
}