// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// @dart = 2.9

library XHRTest;

import 'dart:async';
import 'dart:convert';
import 'dart:html';
import 'dart:typed_data';

import 'package:async_helper/async_minitest.dart';
import 'package:async_helper/async_helper.dart';

// Cache blocker is a workaround for:
// https://code.google.com/p/dart/issues/detail?id=11834
var cacheBlocker = new DateTime.now().millisecondsSinceEpoch;
var url = '/root_dart/tests/lib_2/html/xhr_cross_origin_data.txt?'
    'cacheBlock=$cacheBlocker';

void validate200Response(xhr) {
  expect(xhr.status, 200);
  var data = json.decode(xhr.responseText);
  expect(data.containsKey('feed'), isTrue);
  expect(data['feed'].containsKey('entry'), isTrue);
  expect(data, isMap);
}

void validate404(xhr) {
  expect(xhr.status, 404);
  // We cannot say much about xhr.responseText, most HTTP servers will
  // include an HTML page explaining the error to a human.
  String responseText = xhr.responseText;
  expect(responseText, isNotNull);
}

Future testXhrNoFile() async {
  HttpRequest xhr = new HttpRequest();
  xhr.open("GET", "NonExistingFile", async: true);
  var completer = new Completer<void>();
  xhr.onReadyStateChange.listen((event) {
    if (!completer.isCompleted && xhr.readyState == HttpRequest.DONE) {
      completer.complete();
      validate404(xhr);
    }
  });
  xhr.send();
  await completer;
}

Future testXhrFile() async {
  var loadEndCalled = false;

  var xhr = new HttpRequest();
  xhr.open('GET', url, async: true);
  var completer = new Completer<void>();
  xhr.onReadyStateChange.listen((e) {
    if (!completer.isCompleted && xhr.readyState == HttpRequest.DONE) {
      completer.complete();
      validate200Response(xhr);

      Timer.run(expectAsync(() {
        expect(loadEndCalled, HttpRequest.supportsLoadEndEvent);
      }));
    }
  });

  xhr.onLoadEnd.listen((ProgressEvent e) {
    loadEndCalled = true;
  });
  xhr.send();
  await completer;
}

Future testRequestNoFile() async {
  try {
    await HttpRequest.request('NonExistingFile');
    fail('Request should not have succeeded.');
  } catch (error) {
    HttpRequest xhr = error.target;
    expect(xhr.readyState, HttpRequest.DONE);
    validate404(xhr);
  }
}

Future testRequestFile() async {
  var xhr = await HttpRequest.request(url);
  expect(xhr.readyState, HttpRequest.DONE);
  validate200Response(xhr);
}

Future testRequestOnProgress() async {
  var progressCalled = false;
  var xhr = await HttpRequest.request(url, onProgress: (_) {
    progressCalled = true;
  });
  expect(xhr.readyState, HttpRequest.DONE);
  expect(progressCalled, HttpRequest.supportsProgressEvent);
  validate200Response(xhr);
}

Future testRequestWithCredentialsNoFile() async {
  try {
    await HttpRequest.request('NonExistingFile', withCredentials: true);
    fail('Request should not have succeeded.');
  } catch (error) {
    HttpRequest xhr = error.target;
    expect(xhr.readyState, HttpRequest.DONE);
    validate404(xhr);
  }
}

Future testRequestWithCredentialsFile() async {
  try {
    HttpRequest xhr = await HttpRequest.request(url, withCredentials: true);
    expect(xhr.readyState, HttpRequest.DONE);
    validate200Response(xhr);
  } catch (_) {
    fail('Request should succeed.');
  }
}

Future testGetStringFile() => HttpRequest.getString(url);

Future testGetStringNoFile() async {
  try {
    await HttpRequest.getString('NonExistingFile');
    fail('Succeeded for non-existing file.');
  } catch (error) {
    HttpRequest xhr = error.target;
    expect(xhr.readyState, HttpRequest.DONE);
    validate404(xhr);
  }
}

Future testRequestResponseTypeArrayBuffer() async {
  if (Platform.supportsTypedData) {
    var xhr = await HttpRequest.request(url,
        responseType: 'arraybuffer',
        requestHeaders: {'Content-Type': 'text/xml'});
    expect(xhr.status, 200);
    var byteBuffer = xhr.response;
    expect(byteBuffer, isInstanceOf<ByteBuffer>());
    expect(byteBuffer, isNotNull);
  }
}

Future testOverrideMimeType() async {
  bool gotError = false;
  try {
    await HttpRequest.request(url, mimeType: 'application/binary');
  } catch (_) {
    gotError = true;
  }
  expect(gotError, !HttpRequest.supportsOverrideMimeType);
}

Future testXhrUpload() async {
  if (Platform.supportsTypedData) {
    var xhr = new HttpRequest();
    var progressCalled = false;
    xhr.upload.onProgress.listen((e) {
      progressCalled = true;
    });

    xhr.open(
        'POST', '${window.location.protocol}//${window.location.host}/echo');

    // 10MB of payload data w/ a bit of data to make sure it
    // doesn't get compressed to nil.
    var data = new Uint8List(1 * 1024 * 1024);
    for (var i = 0; i < data.length; ++i) {
      data[i] = i & 0xFF;
    }
    xhr.send(new Uint8List.view(data.buffer));

    await xhr.onLoad.first;
    expect(progressCalled, isTrue, reason: 'onProgress should be fired');
  }
}

Future testXhrPostFormData() async {
  var data = {'name': 'John', 'time': '2 pm'};

  var parts = [];
  for (var key in data.keys) {
    parts.add('${Uri.encodeQueryComponent(key)}='
        '${Uri.encodeQueryComponent(data[key])}');
  }
  var encodedData = parts.join('&');

  var xhr = await HttpRequest.postFormData(
      '${window.location.protocol}//${window.location.host}/echo', data);
  expect(xhr.responseText, encodedData);
}

Future testRequestResponseTypeBlob() async {
  if (Platform.supportsTypedData) {
    var xhr = await HttpRequest.request(url, responseType: 'blob');
    expect(xhr.status, 200);
    var blob = xhr.response;
    expect(blob is Blob, isTrue);
    expect(blob, isNotNull);
  }
}

Future testResponseTypeJson() async {
  var url = '${window.location.protocol}//${window.location.host}/echo';
  var data = {
    'key': 'value',
    'a': 'b',
    'one': 2,
  };

  var xhr = await HttpRequest.request(url,
      method: 'POST', sendData: json.encode(data), responseType: 'json');
  expect(xhr.status, 200);
  var jsonResponse = xhr.response;
  expect(jsonResponse, data);
}

Future testResponseHeaders() async {
  var xhr = await HttpRequest.request(url);
  var contentTypeHeader = xhr.responseHeaders['content-type'];
  expect(contentTypeHeader, isNotNull);
  // Should be like: 'text/plain; charset=utf-8'
  expect(contentTypeHeader.contains('text/plain'), isTrue);
  expect(contentTypeHeader.contains('charset=utf-8'), isTrue);
}

main() {
  test('supportsProgressEvent', () {
    expect(HttpRequest.supportsProgressEvent, isTrue);
  });

  test('supportsOnLoadEnd', () {
    expect(HttpRequest.supportsLoadEndEvent, isTrue);
  });

  test('supportsOverrideMimeType', () {
    expect(HttpRequest.supportsOverrideMimeType, isTrue);
  });

  asyncTest(() async {
    await testXhrNoFile();
    await testXhrFile();
    await testRequestNoFile();
    await testRequestFile();
    await testRequestOnProgress();
    await testRequestWithCredentialsNoFile();
    await testRequestWithCredentialsFile();
    await testGetStringFile();
    await testGetStringNoFile();
    await testRequestResponseTypeArrayBuffer();
    await testOverrideMimeType();
    await testXhrUpload();
    await testXhrPostFormData();

    await testRequestResponseTypeBlob();

    await testResponseTypeJson();

    await testResponseHeaders();
  });
}
