diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8fabf94fe..47592e529 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -39,11 +39,6 @@ jobs: cache: true flutter-version: ${{ matrix.sdk == 'min' && '2.8.0' || '' }} channel: ${{ matrix.sdk == 'min' && '' || matrix.channel }} - - run: | - chmod +x ./scripts/prepare_pinning_certs.sh - ./scripts/prepare_pinning_certs.sh - - name: Install proxy for tests - run: sudo apt-get update && sudo apt-get install -y squid - run: dart pub get - uses: bluefireteam/melos-action@v3 with: @@ -63,6 +58,28 @@ jobs: - name: '[Verify step] Publish dry-run' if: ${{ matrix.sdk == 'stable' }} run: melos run publish-dry-run + # Tests + - run: ./scripts/prepare_pinning_certs.sh + - name: Install proxy for tests + run: sudo apt-get update && sudo apt-get install -y squid mkcert + - name: Start local httpbun + run: | + mkcert -install + mkcert -cert-file '/tmp/cert.pem' -key-file '/tmp/key.pem' httpbun.local + echo '127.0.0.1 httpbun.local' | sudo tee --append /etc/hosts + docker run \ + --name httpbun \ + --detach \ + --publish 443:443 \ + --volume /tmp:/tmp:ro \ + --env HTTPBUN_TLS_CERT=/tmp/cert.pem \ + --env HTTPBUN_TLS_KEY=/tmp/key.pem \ + --pull always \ + sharat87/httpbun + sleep 1 + curl --fail --silent --show-error https://httpbun.local/any + - name: Use local httpbun in tests + run: melos run httpbun:local - name: '[Verify step] Test Dart packages [VM]' run: melos run test:vm - name: '[Verify step] Test Dart packages [Chrome]' @@ -71,6 +88,7 @@ jobs: run: melos run test:web:firefox - name: '[Verify step] Test Flutter packages' run: melos run test:flutter + # Coverage - name: '[Coverage] Format & print test coverage' if: ${{ matrix.sdk == 'stable' }} run: melos run coverage:show diff --git a/dio/test/download_test.dart b/dio/test/download_test.dart index b8fe20f7f..85025b696 100644 --- a/dio/test/download_test.dart +++ b/dio/test/download_test.dart @@ -178,7 +178,7 @@ void main() { expect(f.existsSync(), isTrue); final cancelToken = CancelToken(); - final dio = Dio()..options.baseUrl = 'https://httpbun.com'; + final dio = Dio()..options.baseUrl = httpbunBaseUrl; await expectLater( dio.download( diff --git a/dio/test/test_suite_test.dart b/dio/test/test_suite_test.dart index 750dbb552..1b341d3ca 100644 --- a/dio/test/test_suite_test.dart +++ b/dio/test/test_suite_test.dart @@ -3,6 +3,6 @@ import 'package:dio_test/tests.dart'; void main() { dioAdapterTestSuite( - () => Dio(BaseOptions(baseUrl: 'https://httpbun.com/')), + (baseUrl) => Dio(BaseOptions(baseUrl: baseUrl)), ); } diff --git a/dio/test/timeout_test.dart b/dio/test/timeout_test.dart index ed4747179..ddc243b28 100644 --- a/dio/test/timeout_test.dart +++ b/dio/test/timeout_test.dart @@ -10,7 +10,7 @@ void main() { setUp(() { dio = Dio(); - dio.options.baseUrl = 'https://httpbun.com/'; + dio.options.baseUrl = httpbunBaseUrl; }); group('Timeout exception of', () { diff --git a/dio/test/upload_test.dart b/dio/test/upload_test.dart index 33ddfd183..b4055ccb0 100644 --- a/dio/test/upload_test.dart +++ b/dio/test/upload_test.dart @@ -4,13 +4,14 @@ import 'dart:io'; import 'dart:typed_data'; import 'package:dio/dio.dart'; +import 'package:dio_test/util.dart'; import 'package:test/test.dart'; void main() { late Dio dio; setUp(() { - dio = Dio()..options.baseUrl = 'https://httpbun.com/'; + dio = Dio()..options.baseUrl = httpbunBaseUrl; }); test('Uint8List should not be transformed', () async { diff --git a/dio_test/dart_test.yaml b/dio_test/dart_test.yaml deleted file mode 100644 index 52cfb59fa..000000000 --- a/dio_test/dart_test.yaml +++ /dev/null @@ -1,18 +0,0 @@ -file_reporters: - json: build/reports/test-results.json - -tags: - tls: - skip: "Skipping TLS test with specific setup requirements by default. Use '-P all' to run all tests." - presets: - all: - skip: false - -override_platforms: - chrome: - settings: - headless: true - firefox: - settings: - # headless argument has to be set explicitly for non-chrome browsers - arguments: --headless diff --git a/dio_test/lib/src/httpbun.dart b/dio_test/lib/src/httpbun.dart new file mode 100644 index 000000000..b2e435942 --- /dev/null +++ b/dio_test/lib/src/httpbun.dart @@ -0,0 +1 @@ +const httpbunBaseUrl = 'https://httpbun.com'; diff --git a/dio_test/lib/src/test/cors_tests.dart b/dio_test/lib/src/test/cors_tests.dart index e2da90672..a726a1e1c 100644 --- a/dio_test/lib/src/test/cors_tests.dart +++ b/dio_test/lib/src/test/cors_tests.dart @@ -6,12 +6,12 @@ import 'package:test/test.dart'; /// either "simple" or "preflighted". Reference: /// https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests void corsTests( - Dio Function() create, + Dio Function(String baseUrl) create, ) { late Dio dio; setUp(() { - dio = create(); + dio = create(httpbunBaseUrl); }); group('CORS preflight', () { diff --git a/dio_test/lib/src/test/download_stream_tests.dart b/dio_test/lib/src/test/download_stream_tests.dart index 92a03eada..dce5940ad 100644 --- a/dio_test/lib/src/test/download_stream_tests.dart +++ b/dio_test/lib/src/test/download_stream_tests.dart @@ -2,20 +2,19 @@ import 'dart:async'; import 'dart:io'; import 'package:dio/dio.dart'; +import 'package:dio_test/util.dart'; import 'package:path/path.dart' as p; import 'package:test/test.dart'; -import '../../util.dart'; - void downloadStreamTests( - Dio Function() create, + Dio Function(String baseUrl) create, ) { group('download', () { late Dio dio; late Directory tmp; setUp(() { - dio = create(); + dio = create(httpbunBaseUrl); }); setUpAll(() { @@ -24,6 +23,7 @@ void downloadStreamTests( tmp.deleteSync(recursive: true); }); }); + test('bytes', () async { final path = p.join(tmp.path, 'bytes.txt'); @@ -103,7 +103,7 @@ void downloadStreamTests( test('cancels streamed response mid request', () async { final cancelToken = CancelToken(); final response = await dio.get( - 'bytes/${1024 * 1024 * 100}', + '/bytes/${1024 * 1024 * 100}', options: Options(responseType: ResponseType.stream), cancelToken: cancelToken, onReceiveProgress: (c, t) { @@ -128,7 +128,7 @@ void downloadStreamTests( await expectLater( dio.download( - 'bytes/${1024 * 1024 * 10}', + '/bytes/${1024 * 1024 * 10}', path, cancelToken: cancelToken, onReceiveProgress: (c, t) { diff --git a/dio_test/lib/src/test/headers_tests.dart b/dio_test/lib/src/test/headers_tests.dart index 8724dddae..8cb91a8a8 100644 --- a/dio_test/lib/src/test/headers_tests.dart +++ b/dio_test/lib/src/test/headers_tests.dart @@ -1,13 +1,14 @@ import 'package:dio/dio.dart'; +import 'package:dio_test/util.dart'; import 'package:test/test.dart'; void headerTests( - Dio Function() create, + Dio Function(String baseUrl) create, ) { late Dio dio; - setUpAll(() { - dio = create(); + setUp(() { + dio = create(httpbunBaseUrl); }); group('headers', () { diff --git a/dio_test/lib/src/test/http_method_tests.dart b/dio_test/lib/src/test/http_method_tests.dart index 2240f6503..415ad6f31 100644 --- a/dio_test/lib/src/test/http_method_tests.dart +++ b/dio_test/lib/src/test/http_method_tests.dart @@ -1,14 +1,16 @@ import 'package:dio/dio.dart'; +import 'package:dio_test/util.dart'; import 'package:test/test.dart'; void httpMethodTests( - Dio Function() create, + Dio Function(String baseUrl) create, ) { const data = {'content': 'I am payload'}; late Dio dio; - setUpAll(() { - dio = create(); + + setUp(() { + dio = create(httpbunBaseUrl); }); group('HTTP method', () { diff --git a/dio_test/lib/src/test/parameter_tests.dart b/dio_test/lib/src/test/parameter_tests.dart index 284956ffd..5eca0ad76 100644 --- a/dio_test/lib/src/test/parameter_tests.dart +++ b/dio_test/lib/src/test/parameter_tests.dart @@ -1,13 +1,14 @@ import 'package:dio/dio.dart'; +import 'package:dio_test/util.dart'; import 'package:test/test.dart'; void parameterTests( - Dio Function() create, + Dio Function(String baseUrl) create, ) { late Dio dio; - setUpAll(() { - dio = create(); + setUp(() { + dio = create(httpbunBaseUrl); }); group('parameters', () { diff --git a/dio_test/lib/src/test/redirect_tests.dart b/dio_test/lib/src/test/redirect_tests.dart index 6693a351a..6223cf9de 100644 --- a/dio_test/lib/src/test/redirect_tests.dart +++ b/dio_test/lib/src/test/redirect_tests.dart @@ -1,22 +1,21 @@ import 'package:dio/dio.dart'; +import 'package:dio_test/util.dart'; import 'package:test/test.dart'; -import '../utils.dart'; - void redirectTests( - Dio Function() create, + Dio Function(String baseUrl) create, ) { late Dio dio; - setUpAll(() { - dio = create(); + setUp(() { + dio = create(httpbunBaseUrl); }); group('redirects', () { test('single', () async { final response = await dio.get( '/redirect', - queryParameters: {'url': 'https://httpbun.com/get'}, + queryParameters: {'url': '$httpbunBaseUrl/get'}, onReceiveProgress: (received, total) { // ignore progress }, diff --git a/dio_test/lib/src/test/status_code_tests.dart b/dio_test/lib/src/test/status_code_tests.dart index 391313b51..7b5aa743b 100644 --- a/dio_test/lib/src/test/status_code_tests.dart +++ b/dio_test/lib/src/test/status_code_tests.dart @@ -1,16 +1,14 @@ import 'package:dio/dio.dart'; -import 'package:dio_test/src/utils.dart'; +import 'package:dio_test/util.dart'; import 'package:test/test.dart'; -import '../matcher.dart'; - void statusCodeTests( - Dio Function() create, + Dio Function(String baseUrl) create, ) { late Dio dio; - setUpAll(() { - dio = create(); + setUp(() { + dio = create(httpbunBaseUrl); }); group('status code', () { diff --git a/dio_test/lib/src/test/suite.dart b/dio_test/lib/src/test/suite.dart index 4abc37f8f..5fad692b9 100644 --- a/dio_test/lib/src/test/suite.dart +++ b/dio_test/lib/src/test/suite.dart @@ -2,7 +2,7 @@ import 'package:dio/dio.dart'; import 'package:dio_test/tests.dart'; typedef TestSuiteFunction = void Function( - Dio Function() create, + Dio Function(String baseUrl) create, ); const _tests = [ @@ -17,7 +17,7 @@ const _tests = [ ]; void dioAdapterTestSuite( - Dio Function() create, { + Dio Function(String baseUrl) create, { List tests = _tests, }) => tests.forEach((test) => test(create)); diff --git a/dio_test/lib/src/test/timeout_tests.dart b/dio_test/lib/src/test/timeout_tests.dart index 7bdd86166..23fbbdc5b 100644 --- a/dio_test/lib/src/test/timeout_tests.dart +++ b/dio_test/lib/src/test/timeout_tests.dart @@ -1,18 +1,16 @@ import 'dart:async'; import 'package:dio/dio.dart'; -import 'package:dio_test/src/matcher.dart'; +import 'package:dio_test/util.dart'; import 'package:test/test.dart'; -import '../utils.dart'; - void timeoutTests( - Dio Function() create, + Dio Function(String baseUrl) create, ) { late Dio dio; setUp(() { - dio = create(); + dio = create(httpbunBaseUrl); }); group('Timeout exception of', () { @@ -80,30 +78,26 @@ void timeoutTests( }); test('ignores zero duration timeouts', () async { - final dio = Dio( - BaseOptions( - baseUrl: 'https://httpbun.com/', - connectTimeout: Duration.zero, - receiveTimeout: Duration.zero, - ), - ); + dio.options + ..connectTimeout = Duration.zero + ..receiveTimeout = Duration.zero; // Ignores zero duration timeouts from the base options. await dio.get('/drip-lines?delay=1'); // Reset the base options. - dio.options.receiveTimeout = Duration(milliseconds: 10); + dio.options.receiveTimeout = Duration(milliseconds: 1); await expectLater( dio.get('/drip-lines?delay=1'), throwsDioException( DioExceptionType.receiveTimeout, - messageContains: '0:00:00.010000', + messageContains: dio.options.receiveTimeout.toString(), ), ); - dio.options.connectTimeout = Duration(milliseconds: 10); + dio.options.connectTimeout = Duration(milliseconds: 1); await expectLater( dio.get(nonRoutableUrl), throwsDioException( DioExceptionType.connectionTimeout, - messageContains: '0:00:00.010000', + messageContains: dio.options.connectTimeout.toString(), ), ); dio.options.connectTimeout = Duration.zero; diff --git a/dio_test/lib/util.dart b/dio_test/lib/util.dart index d1e442026..f182df099 100644 --- a/dio_test/lib/util.dart +++ b/dio_test/lib/util.dart @@ -1,2 +1,3 @@ +export 'src/httpbun.dart'; export 'src/matcher.dart'; export 'src/utils.dart'; diff --git a/melos.yaml b/melos.yaml index da6a60073..4148ef614 100644 --- a/melos.yaml +++ b/melos.yaml @@ -41,6 +41,12 @@ scripts: exec: dart pub publish --dry-run packageFilters: noPrivate: true + httpbun:local: + description: Run httpbun locally + run: echo "const httpbunBaseUrl = 'https://httpbun.local';" > dio_test/lib/src/httpbun.dart + httpbun:com: + description: Run httpbun locally + run: echo "const httpbunBaseUrl = 'https://httpbun.com';" > dio_test/lib/src/httpbun.dart test: name: All tests run: | diff --git a/plugins/http2_adapter/test/http2_test.dart b/plugins/http2_adapter/test/http2_test.dart index a936f962e..004916fdf 100644 --- a/plugins/http2_adapter/test/http2_test.dart +++ b/plugins/http2_adapter/test/http2_test.dart @@ -1,11 +1,12 @@ import 'package:dio/dio.dart'; import 'package:dio_http2_adapter/dio_http2_adapter.dart'; +import 'package:dio_test/util.dart'; import 'package:test/test.dart'; void main() { test('works with non-TLS requests', () async { final dio = Dio()..httpClientAdapter = Http2Adapter(ConnectionManager()); - await dio.get('http://flutter.cn/'); + await dio.get('https://flutter.cn/'); await dio.get('https://flutter.cn/non-exist-destination'); }); @@ -56,7 +57,7 @@ void main() { test('adds one to input values', () async { final dio = Dio() - ..options.baseUrl = 'https://httpbun.com/' + ..options.baseUrl = httpbunBaseUrl ..httpClientAdapter = Http2Adapter( ConnectionManager( idleTimeout: Duration(milliseconds: 10), @@ -65,10 +66,10 @@ void main() { ); Response response; - response = await dio.get('get'); + response = await dio.get('/get'); assert(response.statusCode == 200); response = await dio.get( - 'nkjnjknjn.html', + '/nkjnjknjn.html', options: Options(validateStatus: (status) => true), ); assert(response.statusCode == 404); @@ -76,14 +77,14 @@ void main() { test('request with payload', () async { final dio = Dio() - ..options.baseUrl = 'https://httpbun.com/' + ..options.baseUrl = httpbunBaseUrl ..httpClientAdapter = Http2Adapter( ConnectionManager( idleTimeout: Duration(milliseconds: 10), ), ); - final res = await dio.post('post', data: 'TEST'); + final res = await dio.post('/post', data: 'TEST'); expect(res.data.toString(), contains('TEST')); }); @@ -91,14 +92,14 @@ void main() { 'request with payload via proxy', () async { final dio = Dio() - ..options.baseUrl = 'https://httpbun.com/' + ..options.baseUrl = httpbunBaseUrl ..httpClientAdapter = Http2Adapter(ConnectionManager( idleTimeout: Duration(milliseconds: 10), onClientCreate: (uri, settings) => settings.proxy = Uri.parse('http://localhost:3128'), )); - final res = await dio.post('post', data: 'TEST'); + final res = await dio.post('/post', data: 'TEST'); expect(res.data.toString(), contains('TEST')); }, tags: ['proxy'], @@ -107,7 +108,7 @@ void main() { test('request without network and restore', () async { bool needProxy = true; final dio = Dio() - ..options.baseUrl = 'https://httpbun.com/' + ..options.baseUrl = httpbunBaseUrl ..httpClientAdapter = Http2Adapter(ConnectionManager( idleTimeout: Duration(milliseconds: 10), onClientCreate: (uri, settings) { @@ -123,18 +124,18 @@ void main() { )); try { // will throw SocketException - await dio.post('post', data: 'TEST'); + await dio.post('/post', data: 'TEST'); } on DioException { // ignore } - final res = await dio.post('post', data: 'TEST'); + final res = await dio.post('/post', data: 'TEST'); expect(res.data.toString(), contains('TEST')); }); test('catch DioException when receiveTimeout', () { final dio = Dio( BaseOptions( - baseUrl: 'https://httpbun.com/', + baseUrl: httpbunBaseUrl, receiveTimeout: Duration(seconds: 5), ), ); @@ -159,7 +160,7 @@ void main() { test('no DioException when receiveTimeout > request duration', () async { final dio = Dio( BaseOptions( - baseUrl: 'https://httpbun.com/', + baseUrl: httpbunBaseUrl, receiveTimeout: Duration(seconds: 5), ), ); @@ -174,13 +175,13 @@ void main() { group('redirects', () { final dio = Dio() - ..options.baseUrl = 'https://httpbun.com/' + ..options.baseUrl = httpbunBaseUrl ..httpClientAdapter = Http2Adapter(ConnectionManager()); test('single', () async { final response = await dio.get( '/redirect', - queryParameters: {'url': 'https://httpbun.com/get'}, + queryParameters: {'url': '$httpbunBaseUrl/get'}, ); expect(response.isRedirect, isTrue); expect(response.redirects.length, 1); @@ -221,18 +222,18 @@ void main() { }); test('request with redirect', () async { - final res = await dio.get('absolute-redirect/2'); + final res = await dio.get('/absolute-redirect/2'); expect(res.statusCode, 200); }); }); test('header value types implicit support', () async { final dio = Dio() - ..options.baseUrl = 'https://httpbun.com/' + ..options.baseUrl = httpbunBaseUrl ..httpClientAdapter = Http2Adapter(ConnectionManager()); final res = await dio.post( - 'post', + '/post', data: 'TEST', options: Options( headers: { diff --git a/plugins/http2_adapter/test/test_suite_test.dart b/plugins/http2_adapter/test/test_suite_test.dart index fe6f76d2e..5c7e907ae 100644 --- a/plugins/http2_adapter/test/test_suite_test.dart +++ b/plugins/http2_adapter/test/test_suite_test.dart @@ -4,7 +4,7 @@ import 'package:dio_test/tests.dart'; void main() { dioAdapterTestSuite( - () => Dio(BaseOptions(baseUrl: 'https://httpbun.com/')) + (baseUrl) => Dio(BaseOptions(baseUrl: baseUrl)) ..httpClientAdapter = Http2Adapter(ConnectionManager()), ); } diff --git a/scripts/prepare_pinning_certs.sh b/scripts/prepare_pinning_certs.sh old mode 100644 new mode 100755