'use strict';

const loaderUtils = require('../');

function ExpectedError(regex) {
  this.regex = regex;
}

ExpectedError.prototype.matches = function(err) {
  return this.regex.test(err.message);
};

describe('urlToRequest()', () => {
  [
    // without root
    [
      ['path/to/thing'],
      './path/to/thing',
      'should handle implicit relative urls',
    ],
    [
      ['./path/to/thing'],
      './path/to/thing',
      'should handle explicit relative urls',
    ],
    [['~path/to/thing'], 'path/to/thing', 'should handle module urls (with ~)'],
    [
      ['some/other/stuff/and/then~path/to/thing'],
      'path/to/thing',
      'should handle module urls with path prefix',
    ],
    [
      ['./some/other/stuff/and/then~path/to/thing'],
      'path/to/thing',
      'should handle module urls with relative path prefix',
    ],
    // with root (normal path)
    [
      ['path/to/thing', 'root/dir'],
      './path/to/thing',
      'should do nothing with root if implicit relative url',
    ],
    [
      ['./path/to/thing', 'root/dir'],
      './path/to/thing',
      'should do nothing with root if explicit relative url',
    ],
    [
      ['/path/to/thing', 'root/dir'],
      'root/dir/path/to/thing',
      'should include root if root-relative url',
    ],
    // with root (boolean)
    [
      ['/path/to/thing', true],
      '/path/to/thing',
      'should allow root-relative to exist as-is if root = `true`',
    ],
    // with root (boolean) on Windows
    [
      ['C:\\path\\to\\thing'],
      'C:\\path\\to\\thing',
      'should handle Windows absolute paths with drive letter',
    ],
    [
      ['\\\\?\\UNC\\ComputerName\\path\\to\\thing'],
      '\\\\?\\UNC\\ComputerName\\path\\to\\thing',
      'should handle Windows absolute UNC paths',
    ],
    // with root (module)
    [
      ['/path/to/thing', '~'],
      'path/to/thing',
      'should convert to module url if root = ~',
    ],
    // with root (module path)
    [
      ['/path/to/thing', '~module'],
      'module/path/to/thing',
      'should allow module prefixes when root starts with ~',
    ],
    [
      ['/path/to/thing', '~module/'],
      'module/path/to/thing',
      'should allow module prefixes (with trailing slash) when root starts with ~',
    ],
    // error cases
    [
      ['/path/to/thing', 1],
      new ExpectedError(/unexpected parameters/i),
      'should throw an error on invalid root',
    ],
    // difficult cases
    [
      ['a:b-not-\\window-path'],
      './a:b-not-\\window-path',
      'should not incorrectly detect windows paths',
    ],
    // empty url
    [[''], '', 'should do nothing if url is empty'],
  ].forEach((test) => {
    it(test[2], () => {
      const expected = test[1];

      try {
        const request = loaderUtils.urlToRequest.apply(loaderUtils, test[0]);

        expect(request).toBe(expected);
      } catch (e) {
        if (expected instanceof ExpectedError) {
          expect(expected.matches(e)).toBe(true);
        } else {
          throw new Error('should not have thrown an error: ' + e.message);
        }
      }
    });
  });
});
