// Copyright (c) 2014, 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.

import 'package:test/test.dart';
import 'package:source_span/source_span.dart';

main() {
  var location;
  setUp(() {
    location = new SourceLocation(15,
        line: 2, column: 6, sourceUrl: "foo.dart");
  });

  group('errors', () {
    group('for new SourceLocation()', () {
      test('offset may not be negative', () {
        expect(() => new SourceLocation(-1), throwsRangeError);
      });

      test('line may not be negative', () {
        expect(() => new SourceLocation(0, line: -1), throwsRangeError);
      });

      test('column may not be negative', () {
        expect(() => new SourceLocation(0, column: -1), throwsRangeError);
      });
    });

    test('for distance() source URLs must match', () {
      expect(() => location.distance(new SourceLocation(0)),
          throwsArgumentError);
    });

    test('for compareTo() source URLs must match', () {
      expect(() => location.compareTo(new SourceLocation(0)),
          throwsArgumentError);
    });
  });

  test('fields work correctly', () {
    expect(location.sourceUrl, equals(Uri.parse("foo.dart")));
    expect(location.offset, equals(15));
    expect(location.line, equals(2));
    expect(location.column, equals(6));
  });

  group('toolString', () {
    test('returns a computer-readable representation', () {
      expect(location.toolString, equals('foo.dart:3:7'));
    });

    test('gracefully handles a missing source URL', () {
      var location = new SourceLocation(15, line: 2, column: 6);
      expect(location.toolString, equals('unknown source:3:7'));
    });
  });

  test("distance returns the absolute distance between locations", () {
    var other = new SourceLocation(10, sourceUrl: "foo.dart");
    expect(location.distance(other), equals(5));
    expect(other.distance(location), equals(5));
  });

  test("pointSpan returns an empty span at location", () {
    var span = location.pointSpan();
    expect(span.start, equals(location));
    expect(span.end, equals(location));
    expect(span.text, isEmpty);
  });

  group("compareTo()", () {
    test("sorts by offset", () {
      var other = new SourceLocation(20, sourceUrl: "foo.dart");
      expect(location.compareTo(other), lessThan(0));
      expect(other.compareTo(location), greaterThan(0));
    });

    test("considers equal locations equal", () {
      expect(location.compareTo(location), equals(0));
    });
  });


  group("equality", () {
    test("two locations with the same offset and source are equal", () {
      var other = new SourceLocation(15, sourceUrl: "foo.dart");
      expect(location, equals(other));
    });

    test("a different offset isn't equal", () {
      var other = new SourceLocation(10, sourceUrl: "foo.dart");
      expect(location, isNot(equals(other)));
    });

    test("a different source isn't equal", () {
      var other = new SourceLocation(15, sourceUrl: "bar.dart");
      expect(location, isNot(equals(other)));
    });
  });
}
