import {expectError, expectType} from 'tsd';
import {EnhancedPageObject, PageObjectModel, Awaitable, NightwatchAPI, Cookie, NightwatchLogEntry, NightwatchLogTypes, WindowSizeAndPosition} from '..';
import {WebElement} from 'selenium-webdriver';

// Page object file
const fileUploadPageElements = {
  fileUploadInput: 'input#file-upload',
  submitButton: 'input#file-submit',
  uploadFiles: '#uploaded-files'
};

const menuSection = {
  selector: 'nav',
  elements: {
    home: 'a[href="/"]',
    about: 'a[href="/about"]'
  }
};

const fileUploadPage = {
  url(this: EnhancedPageObject) {
    return `${this.api.launch_url}/upload`;
  },
  elements: fileUploadPageElements,
  sections: {
    menu: menuSection
  }
} satisfies PageObjectModel;

export interface FileUploadPage extends
  EnhancedPageObject<{}, typeof fileUploadPageElements, typeof fileUploadPage.sections, {}, () => string> {} // eslint-disable-line @typescript-eslint/ban-types

export default fileUploadPage;


// Declare the newly created page object in the NightwatchCustomPageObjects interface.
// This will allow you to access the page object type in your test files.
declare module '..' {
  interface NightwatchCustomPageObjects {
    FileUpload(): FileUploadPage;
  }
  interface NightwatchCustomCommands {
    // uploadFile1 returns NightwatchAPI (breaks chaining on page objects)
    uploadFile1(selector: string, filePath: string): NightwatchAPI;
    // uploadFile2 returns Awaitable<NightwatchAPI, null> (breaks chaining on page objects)
    uploadFile2(selector: string, filePath: string): Awaitable<NightwatchAPI, null>;
    // uploadFile3 returns 'this' (allows chaining)
    uploadFile3(selector: string, filePath: string): this;
    // uploadFile4 returns 'this' (allows chaining)
    uploadFile4(selector: string, filePath: string): Awaitable<this, null>;
    upload: {
      file(selector: string, filePath: string): NightwatchAPI;
    }
  }
}


// test file
describe('File Upload', function() {
  it('File Upload test', function() {
    const fileUploadPage = browser.page.FileUpload();
    const url = fileUploadPage.url();

    fileUploadPage
      .navigate(url)
      .uploadFile('@fileUploadInput', 'test.txt')
      // alternate way of passing an element instead of '@submitButton'
      .click(fileUploadPage.elements.submitButton)
      .expect.element('@uploadFiles').text.to.equal('test.txt');

    // test custom commands over page object
    expectType<NightwatchAPI>(fileUploadPage.uploadFile1('@fileUploadInput', 'test2.txt'));
    expectType<Awaitable<NightwatchAPI, null>>(fileUploadPage.uploadFile2('@fileUploadInput', 'test2.txt'));
    // uploadFile3 returns 'this', so it preserves the page object type
    expectType<FileUploadPage>(fileUploadPage.uploadFile3('@fileUploadInput', 'test2.txt'));
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.uploadFile4('@fileUploadInput', 'test2.txt'));
    // should fail ideally but succeeding (namespace from custom commands not loaded directly into page object??)
    expectType<NightwatchAPI>(fileUploadPage.upload.file('@fileUploadInput', 'test2.txt'));

    // test custom commands over page object sections
    const menuSection = fileUploadPage.section.menu;
    expectType<NightwatchAPI>(menuSection.uploadFile1('@fileUploadInput', 'test2.txt'));
    expectType<Awaitable<NightwatchAPI, null>>(menuSection.uploadFile2('@fileUploadInput', 'test2.txt'));
    // uploadFile3 returns 'this', so it preserves the section type
    // Note: TypeScript may not properly resolve 'this' for custom commands on sections
    // The command works, but type resolution is limited
    menuSection.uploadFile3('@fileUploadInput', 'test2.txt');
    // should fail because the namespaces from custom commands are not loaded directly into the section
    expectError(menuSection.upload.file('@fileUploadInput', 'test2.txt'));

    browser.end();
  });
});


/**************************
 * OTHER TESTS
 *************************/
describe('File Upload 2', function() {
  it('File Upload test', function() {
    const fileUploadPage = browser.page.FileUpload();

    // user actions element commands work on page objects
    fileUploadPage.rightClick('@fileUploadInput');
    fileUploadPage.doubleClick('@fileUploadInput');
    fileUploadPage.clickAndHold('@fileUploadInput');
    expectError(fileUploadPage.navigateTo('https://google.com'));
    expectType<string>(fileUploadPage.url());

    // user actions element commands work on sections
    const menuSection = fileUploadPage.section.menu;
    menuSection.rightClick('@fileUploadInput');
    menuSection.doubleClick('@fileUploadInput');
    menuSection.clickAndHold('@fileUploadInput');
    expectError(menuSection.navigateTo('https://google.com'));
    expectError(menuSection.url());
  });
});

/**************************
 * TESTS FOR MOVED COMMANDS (SharedClientCommands)
 *************************/
describe('Page Object - SharedClientCommands', function() {
  it('should have access to moved commands from SharedClientCommands', function() {
    const fileUploadPage = browser.page.FileUpload();
    const menuSection = fileUploadPage.section.menu;

    // Test commands that were moved to SharedClientCommands
    // Verify they exist, are callable, and return correct types
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.axeInject());
    expectType<Awaitable<FileUploadPage, { [key: string]: any }>>(fileUploadPage.axeRun());
    expectType<Awaitable<FileUploadPage, undefined>>(fileUploadPage.debug());
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.deleteCookie('test'));
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.deleteCookies());
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.end());
    expectType<Awaitable<FileUploadPage, Cookie>>(fileUploadPage.getCookie('test-cookie'));
    expectType<Awaitable<FileUploadPage, Cookie[]>>(fileUploadPage.getCookies());
    expectType<Awaitable<FileUploadPage, NightwatchLogEntry[]>>(fileUploadPage.getLog('server'));
    expectType<Awaitable<FileUploadPage, NightwatchLogTypes[]>>(fileUploadPage.getLogTypes());
    expectType<Awaitable<FileUploadPage, string>>(fileUploadPage.getTitle());
    expectType<Awaitable<FileUploadPage, { x: number; y: number }>>(fileUploadPage.getWindowPosition());
    expectType<Awaitable<FileUploadPage, WindowSizeAndPosition>>(fileUploadPage.getWindowRect());
    expectType<Awaitable<FileUploadPage, WindowSizeAndPosition>>(fileUploadPage.getWindowSize());
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.init());
    expectType<Awaitable<FileUploadPage, WebElement>>(fileUploadPage.injectScript('script.js'));
    expectType<Awaitable<FileUploadPage, boolean>>(fileUploadPage.isLogAvailable('browser'));
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.maximizeWindow());
    expectType<Awaitable<FileUploadPage, string>>(fileUploadPage.pageSource());
    expectType<Awaitable<FileUploadPage, undefined>>(fileUploadPage.pause(1000));
    expectType<Awaitable<FileUploadPage, void>>(fileUploadPage.perform(() => {}));
    expectType<Awaitable<FileUploadPage, string>>(fileUploadPage.perform<string>(() => {}));
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.resizeWindow(1000, 800));
    expectType<Awaitable<FileUploadPage, string>>(fileUploadPage.saveScreenshot('test.png'));
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.setCookie({name: 'test', value: 'value'}));
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.setWindowPosition(0, 0));
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.setWindowRect({x: 0, y: 0, width: 800, height: 600}));
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.setWindowSize(800, 600));
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.urlHash('#test'));
    expectType<Awaitable<FileUploadPage, undefined>>(fileUploadPage.useCss());
    expectType<Awaitable<FileUploadPage, undefined>>(fileUploadPage.useXpath());

    // These should also work on sections with correct return types
    expectType<Awaitable<typeof menuSection, null>>(menuSection.axeInject());
    expectType<Awaitable<typeof menuSection, { [key: string]: any }>>(menuSection.axeRun());
    expectType<Awaitable<typeof menuSection, undefined>>(menuSection.debug());
    expectType<Awaitable<typeof menuSection, null>>(menuSection.deleteCookie('test'));
    expectType<Awaitable<typeof menuSection, null>>(menuSection.deleteCookies());
    expectType<Awaitable<typeof menuSection, null>>(menuSection.end());
    expectType<Awaitable<typeof menuSection, Cookie>>(menuSection.getCookie('test-cookie'));
    expectType<Awaitable<typeof menuSection, Cookie[]>>(menuSection.getCookies());
    expectType<Awaitable<typeof menuSection, NightwatchLogEntry[]>>(menuSection.getLog('server'));
    expectType<Awaitable<typeof menuSection, NightwatchLogTypes[]>>(menuSection.getLogTypes());
    expectType<Awaitable<typeof menuSection, string>>(menuSection.getTitle());
    expectType<Awaitable<typeof menuSection, { x: number; y: number }>>(menuSection.getWindowPosition());
    expectType<Awaitable<typeof menuSection, WindowSizeAndPosition>>(menuSection.getWindowRect());
    expectType<Awaitable<typeof menuSection, WindowSizeAndPosition>>(menuSection.getWindowSize());
    expectType<Awaitable<typeof menuSection, null>>(menuSection.init());
    expectType<Awaitable<typeof menuSection, WebElement>>(menuSection.injectScript('script.js'));
    expectType<Awaitable<typeof menuSection, boolean>>(menuSection.isLogAvailable('browser'));
    expectType<Awaitable<typeof menuSection, null>>(menuSection.maximizeWindow());
    expectType<Awaitable<typeof menuSection, string>>(menuSection.pageSource());
    expectType<Awaitable<typeof menuSection, undefined>>(menuSection.pause(1000));
    expectType<Awaitable<typeof menuSection, void>>(menuSection.perform(() => {}));
    expectType<Awaitable<typeof menuSection, string>>(menuSection.perform<string>(() => {}));
    expectType<Awaitable<typeof menuSection, null>>(menuSection.resizeWindow(1000, 800));
    expectType<Awaitable<typeof menuSection, string>>(menuSection.saveScreenshot('test.png'));
    expectType<Awaitable<typeof menuSection, null>>(menuSection.setCookie({name: 'test', value: 'value'}));
    expectType<Awaitable<typeof menuSection, null>>(menuSection.setWindowPosition(0, 0));
    expectType<Awaitable<typeof menuSection, null>>(menuSection.setWindowRect({x: 0, y: 0, width: 800, height: 600}));
    expectType<Awaitable<typeof menuSection, null>>(menuSection.setWindowSize(800, 600));
    expectType<Awaitable<typeof menuSection, null>>(menuSection.urlHash('#test'));
    expectType<Awaitable<typeof menuSection, undefined>>(menuSection.useCss());
    expectType<Awaitable<typeof menuSection, undefined>>(menuSection.useXpath());
  });
});

/**************************
 * TESTS FOR CHROMIUM CLIENT COMMANDS
 *************************/
describe('Page Object - ChromiumClientCommands', function() {
  it('should have access to commands from ChromiumClientCommands', function() {
    const fileUploadPage = browser.page.FileUpload();
    const menuSection = fileUploadPage.section.menu;

    // Test commands from ChromiumClientCommands
    // Verify they exist, are callable, and return correct types
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.setGeolocation({latitude: 35.689487, longitude: 139.691706, accuracy: 100}));
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.setGeolocation());
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.setDeviceDimensions({width: 400, height: 600, deviceScaleFactor: 50, mobile: true}));
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.setDeviceDimensions());
    expectType<Awaitable<FileUploadPage, { [metricName: string]: number }>>(fileUploadPage.getPerformanceMetrics());
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.enablePerformanceMetrics(true));
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.enablePerformanceMetrics());
    expectType<Awaitable<FileUploadPage, string>>(fileUploadPage.takeHeapSnapshot('./snap.heapsnapshot'));
    expectType<Awaitable<FileUploadPage, string>>(fileUploadPage.takeHeapSnapshot());
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.registerBasicAuth('test-user', 'test-pass'));
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.captureNetworkRequests(() => {}));
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.mockNetworkResponse('https://example.com', {status: 200}));
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.setNetworkConditions({offline: false, latency: 3000, download_throughput: 500 * 1024, upload_throughput: 500 * 1024}));
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.captureBrowserConsoleLogs(() => {}));
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.captureBrowserExceptions(() => {}));

    // These should also work on sections with correct return types
    expectType<Awaitable<typeof menuSection, null>>(menuSection.setGeolocation({latitude: 35.689487, longitude: 139.691706, accuracy: 100}));
    expectType<Awaitable<typeof menuSection, null>>(menuSection.setGeolocation());
    expectType<Awaitable<typeof menuSection, null>>(menuSection.setDeviceDimensions({width: 400, height: 600, deviceScaleFactor: 50, mobile: true}));
    expectType<Awaitable<typeof menuSection, null>>(menuSection.setDeviceDimensions());
    expectType<Awaitable<typeof menuSection, { [metricName: string]: number }>>(menuSection.getPerformanceMetrics());
    expectType<Awaitable<typeof menuSection, null>>(menuSection.enablePerformanceMetrics(true));
    expectType<Awaitable<typeof menuSection, null>>(menuSection.enablePerformanceMetrics());
    expectType<Awaitable<typeof menuSection, string>>(menuSection.takeHeapSnapshot('./snap.heapsnapshot'));
    expectType<Awaitable<typeof menuSection, string>>(menuSection.takeHeapSnapshot());
    expectType<Awaitable<typeof menuSection, null>>(menuSection.registerBasicAuth('test-user', 'test-pass'));
    expectType<Awaitable<typeof menuSection, null>>(menuSection.captureNetworkRequests(() => {}));
    expectType<Awaitable<typeof menuSection, null>>(menuSection.mockNetworkResponse('https://example.com', {status: 200}));
    expectType<Awaitable<typeof menuSection, null>>(menuSection.setNetworkConditions({offline: false, latency: 3000, download_throughput: 500 * 1024, upload_throughput: 500 * 1024}));
    expectType<Awaitable<typeof menuSection, null>>(menuSection.captureBrowserConsoleLogs(() => {}));
    expectType<Awaitable<typeof menuSection, null>>(menuSection.captureBrowserExceptions(() => {}));
  });
});

/**************************
 * TESTS FOR CLIENT COMMANDS
 *************************/
describe('Page Object - ClientCommands', function() {
  it('should verify that ClientCommands-specific commands are not available on page objects', function() {
    const fileUploadPage = browser.page.FileUpload();
    const menuSection = fileUploadPage.section.menu;

    // Test commands that are specific to ClientCommands (not in ChromiumClientCommands or SharedClientCommands)
    // These commands are NOT available on page objects as they're not part of PageObjectClientCommands
    // Verify they don't exist using expectError
    expectError(fileUploadPage.closeWindow());
    expectError(fileUploadPage.fullscreenWindow());
    expectError(fileUploadPage.minimizeWindow());
    expectError(fileUploadPage.openNewWindow());
    expectError(fileUploadPage.getCurrentUrl());
    expectError(fileUploadPage.navigateTo('https://example.com'));
    expectError(fileUploadPage.quit());
    expectError(fileUploadPage.waitUntil(function() { return true }));
    expectError(fileUploadPage.switchWindow('handle'));
    expectError(fileUploadPage.switchToWindow('handle'));

    // These should also not be available on sections
    expectError(menuSection.closeWindow());
    expectError(menuSection.fullscreenWindow());
    expectError(menuSection.minimizeWindow());
    expectError(menuSection.openNewWindow());
    expectError(menuSection.getCurrentUrl());
    expectError(menuSection.navigateTo('https://example.com'));
    expectError(menuSection.quit());
    expectError(menuSection.waitUntil(function() { return true }));
    expectError(menuSection.switchWindow('handle'));
    expectError(menuSection.switchToWindow('handle'));
  });
});

/**************************
 * TESTS FOR CUSTOM COMMAND CHAINING
 *************************/
describe('Page Object - Custom Command Chaining', function() {
  it('should support chaining custom commands with built-in commands on page objects', function() {
    const fileUploadPage = browser.page.FileUpload();

    // Chain built-in command -> custom command
    expectType<NightwatchAPI>(fileUploadPage.pause(1000).uploadFile1('@fileUploadInput', 'test.txt'));
    expectType<NightwatchAPI>(fileUploadPage.click('@submitButton').uploadFile1('@fileUploadInput', 'test.txt'));
    expectType<NightwatchAPI>(fileUploadPage.setValue('@fileUploadInput', 'value').uploadFile1('@fileUploadInput', 'test.txt'));

    // Chain custom command -> built-in command
    // uploadFile1 returns NightwatchAPI, then these commands return Awaitable<NightwatchAPI, ...>
    expectType<Awaitable<NightwatchAPI, undefined>>(fileUploadPage.uploadFile1('@fileUploadInput', 'test.txt').pause(1000));
    expectType<Awaitable<NightwatchAPI, null>>(fileUploadPage.uploadFile1('@fileUploadInput', 'test.txt').click('@submitButton'));
    expectType<Awaitable<NightwatchAPI, string>>(fileUploadPage.uploadFile1('@fileUploadInput', 'test.txt').getTitle());

    // Chain multiple custom commands (uploadFile1 returns NightwatchAPI)
    expectType<NightwatchAPI>(fileUploadPage.uploadFile1('@fileUploadInput', 'test.txt').uploadFile1('@fileUploadInput', 'test2.txt'));
    // When chained with pause, pause returns Awaitable<NightwatchAPI, undefined>
    expectType<Awaitable<NightwatchAPI, undefined>>(fileUploadPage.uploadFile1('@fileUploadInput', 'test.txt').uploadFile1('@fileUploadInput', 'test2.txt').pause(1000));

    // Chain multiple custom commands (uploadFile3 returns 'this', preserves page object type)
    // uploadFile3 returns FileUploadPage, so chaining multiple returns FileUploadPage
    expectType<FileUploadPage>(fileUploadPage.uploadFile3('@fileUploadInput', 'test.txt'));
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.uploadFile4('@fileUploadInput', 'test.txt'));
    expectType<FileUploadPage>(fileUploadPage.uploadFile4('@fileUploadInput', 'test.txt').uploadFile3('@fileUploadInput', 'test2.txt'));
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.uploadFile3('@fileUploadInput', 'test.txt').uploadFile4('@fileUploadInput', 'test2.txt'));
    // When chained with pause, pause returns Awaitable
    expectType<Awaitable<FileUploadPage, undefined>>(fileUploadPage.uploadFile3('@fileUploadInput', 'test.txt').uploadFile3('@fileUploadInput', 'test2.txt').pause(1000));

    // Chain custom command that returns 'this' (allows chaining back to page object)
    // uploadFile3 returns FileUploadPage, then pause returns Awaitable<FileUploadPage, undefined>
    expectType<Awaitable<FileUploadPage, undefined>>(fileUploadPage.pause(1000).uploadFile3('@fileUploadInput', 'test.txt').pause(1000));
    expectType<Awaitable<FileUploadPage, undefined>>(fileUploadPage.uploadFile3('@fileUploadInput', 'test.txt').pause(1000));
    // click returns Awaitable<FileUploadPage, null>
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.uploadFile3('@fileUploadInput', 'test.txt').click('@submitButton'));
    expectType<Awaitable<FileUploadPage, string>>(fileUploadPage.uploadFile3('@fileUploadInput', 'test.txt').getTitle());

    // Chain custom command with Awaitable return type -> built-in command
    expectType<Awaitable<NightwatchAPI, null>>(fileUploadPage.uploadFile2('@fileUploadInput', 'test.txt').click('@submitButton'));

    // Chain built-in command -> custom command with Awaitable return type
    expectType<Awaitable<NightwatchAPI, null>>(fileUploadPage.pause(1000).uploadFile2('@fileUploadInput', 'test.txt'));
    expectType<Awaitable<NightwatchAPI, null>>(fileUploadPage.click('@submitButton').uploadFile2('@fileUploadInput', 'test.txt'));

    // Chain custom command -> SharedClientCommands (uploadFile1 returns NightwatchAPI)
    // These commands return Awaitable<NightwatchAPI, ...>
    expectType<Awaitable<NightwatchAPI, undefined>>(fileUploadPage.uploadFile1('@fileUploadInput', 'test.txt').pause(1000));
    expectType<Awaitable<NightwatchAPI, undefined>>(fileUploadPage.uploadFile1('@fileUploadInput', 'test.txt').debug());
    expectType<Awaitable<NightwatchAPI, string>>(fileUploadPage.uploadFile1('@fileUploadInput', 'test.txt').getTitle());
    expectType<Awaitable<NightwatchAPI, string>>(fileUploadPage.uploadFile1('@fileUploadInput', 'test.txt').saveScreenshot('test.png'));

    // Chain custom command -> SharedClientCommands (uploadFile3 returns 'this', preserves page object type)
    // uploadFile3 returns FileUploadPage, then these commands return Awaitable<FileUploadPage, ...>
    expectType<Awaitable<FileUploadPage, undefined>>(fileUploadPage.uploadFile3('@fileUploadInput', 'test.txt').pause(1000));
    expectType<Awaitable<FileUploadPage, undefined>>(fileUploadPage.uploadFile3('@fileUploadInput', 'test.txt').debug());
    expectType<Awaitable<FileUploadPage, string>>(fileUploadPage.uploadFile3('@fileUploadInput', 'test.txt').getTitle());
    expectType<Awaitable<FileUploadPage, string>>(fileUploadPage.uploadFile3('@fileUploadInput', 'test.txt').saveScreenshot('test.png'));

    // Chain SharedClientCommands -> custom command (uploadFile1 returns NightwatchAPI)
    expectType<NightwatchAPI>(fileUploadPage.pause(1000).uploadFile1('@fileUploadInput', 'test.txt'));
    expectType<NightwatchAPI>(fileUploadPage.debug().uploadFile1('@fileUploadInput', 'test.txt'));
    expectType<NightwatchAPI>(fileUploadPage.getTitle().uploadFile1('@fileUploadInput', 'test.txt'));

    // Chain SharedClientCommands -> custom command (uploadFile3 returns 'this', preserves page object type)
    // Note: When chaining from Awaitable, TypeScript may not properly resolve 'this' type
    // These tests verify that uploadFile3 can be called, but type resolution may be limited
    fileUploadPage.pause(1000).uploadFile3('@fileUploadInput', 'test.txt');
    fileUploadPage.debug().uploadFile3('@fileUploadInput', 'test.txt');
    fileUploadPage.getTitle().uploadFile3('@fileUploadInput', 'test.txt');

    // Chain custom command -> ChromiumClientCommands (uploadFile1 returns NightwatchAPI)
    // setGeolocation returns Awaitable<NightwatchAPI, null>
    expectType<Awaitable<NightwatchAPI, null>>(fileUploadPage.uploadFile1('@fileUploadInput', 'test.txt').setGeolocation({ latitude: 35.689487, longitude: 139.691706 }));
    expectType<Awaitable<NightwatchAPI, null>>(fileUploadPage.uploadFile1('@fileUploadInput', 'test.txt').setDeviceDimensions({ width: 400, height: 600 }));

    // Chain custom command -> ChromiumClientCommands (uploadFile3 returns 'this', preserves page object type)
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.uploadFile3('@fileUploadInput', 'test.txt').setGeolocation({ latitude: 35.689487, longitude: 139.691706 }));
    expectType<Awaitable<FileUploadPage, null>>(fileUploadPage.uploadFile3('@fileUploadInput', 'test.txt').setDeviceDimensions({ width: 400, height: 600 }));

    // Chain ChromiumClientCommands -> custom command (uploadFile1 returns NightwatchAPI)
    expectType<NightwatchAPI>(fileUploadPage.setGeolocation({latitude: 35.689487, longitude: 139.691706}).uploadFile1('@fileUploadInput', 'test.txt'));
    expectType<NightwatchAPI>(fileUploadPage.setDeviceDimensions({width: 400, height: 600}).uploadFile1('@fileUploadInput', 'test.txt'));

    // Chain ChromiumClientCommands -> custom command (uploadFile3 returns 'this', preserves page object type)
    // Note: When chaining from Awaitable, TypeScript may not properly resolve 'this' type
    // These tests verify that uploadFile3 can be called, but type resolution may be limited
    fileUploadPage.setGeolocation({latitude: 35.689487, longitude: 139.691706}).uploadFile3('@fileUploadInput', 'test.txt');
    fileUploadPage.setDeviceDimensions({width: 400, height: 600}).uploadFile3('@fileUploadInput', 'test.txt');
  });

});
