| // 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. |
| |
| library pub_lish_test; |
| |
| import 'dart:io'; |
| import 'dart:json' as json; |
| |
| import '../../../pkg/scheduled_test/lib/scheduled_test.dart'; |
| import '../../../pkg/scheduled_test/lib/scheduled_server.dart'; |
| |
| import '../../pub/exit_codes.dart' as exit_codes; |
| import '../../pub/io.dart'; |
| import 'descriptor.dart' as d; |
| import 'test_pub.dart'; |
| |
| void handleUploadForm(ScheduledServer server, [Map body]) { |
| server.handle('GET', '/packages/versions/new.json', (request) { |
| return server.url.then((url) { |
| expect(request.headers.value('authorization'), |
| equals('Bearer access token')); |
| |
| if (body == null) { |
| body = { |
| 'url': url.resolve('/upload').toString(), |
| 'fields': { |
| 'field1': 'value1', |
| 'field2': 'value2' |
| } |
| }; |
| } |
| |
| request.response.headers.contentType = |
| new ContentType("application", "json"); |
| request.response.write(json.stringify(body)); |
| request.response.close(); |
| }); |
| }); |
| } |
| |
| void handleUpload(ScheduledServer server) { |
| server.handle('POST', '/upload', (request) { |
| // TODO(nweiz): Once a multipart/form-data parser in Dart exists, validate |
| // that the request body is correctly formatted. See issue 6952. |
| return drainStream(request).then((_) { |
| return server.url; |
| }).then((url) { |
| request.response.statusCode = 302; |
| request.response.headers.set( |
| 'location', url.resolve('/create').toString()); |
| request.response.close(); |
| }); |
| }); |
| } |
| |
| main() { |
| initConfig(); |
| setUp(() => d.validPackage.create()); |
| |
| integration('archives and uploads a package', () { |
| var server = new ScheduledServer(); |
| d.credentialsFile(server, 'access token').create(); |
| var pub = startPublish(server); |
| |
| confirmPublish(pub); |
| handleUploadForm(server); |
| handleUpload(server); |
| |
| server.handle('GET', '/create', (request) { |
| request.response.write(json.stringify({ |
| 'success': {'message': 'Package test_pkg 1.0.0 uploaded!'} |
| })); |
| request.response.close(); |
| }); |
| |
| // TODO(rnystrom): The confirm line is run together with this one because |
| // in normal usage, the user will have entered a newline on stdin which |
| // gets echoed to the terminal. Do something better here? |
| expect(pub.nextLine(), completion(equals( |
| 'Looks great! Are you ready to upload your package (y/n)?' |
| ' Package test_pkg 1.0.0 uploaded!'))); |
| pub.shouldExit(0); |
| }); |
| |
| // TODO(nweiz): Once a multipart/form-data parser in Dart exists, we should |
| // test that "pub lish" chooses the correct files to publish. |
| |
| integration('package validation has an error', () { |
| var pkg = packageMap("test_pkg", "1.0.0"); |
| pkg.remove("homepage"); |
| d.dir(appPath, [d.pubspec(pkg)]).create(); |
| |
| var server = new ScheduledServer(); |
| var pub = startPublish(server); |
| |
| pub.shouldExit(0); |
| expect(pub.remainingStderr(), completion(contains( |
| "Sorry, your package is missing a requirement and can't be published " |
| "yet."))); |
| }); |
| |
| integration('preview package validation has a warning', () { |
| var pkg = packageMap("test_pkg", "1.0.0"); |
| pkg["author"] = "Nathan Weizenbaum"; |
| d.dir(appPath, [d.pubspec(pkg)]).create(); |
| |
| var server = new ScheduledServer(); |
| var pub = startPublish(server, args: ['--dry-run']); |
| |
| pub.shouldExit(0); |
| expect(pub.remainingStderr(), completion(contains( |
| 'Suggestions:\n* Author "Nathan Weizenbaum" in pubspec.yaml should ' |
| 'have an email address\n' |
| ' (e.g. "name <email>").\n\n' |
| 'Package has 1 warning.'))); |
| }); |
| |
| integration('preview package validation has no warnings', () { |
| var pkg = packageMap("test_pkg", "1.0.0"); |
| pkg["author"] = "Nathan Weizenbaum <nweiz@google.com>"; |
| d.dir(appPath, [d.pubspec(pkg)]).create(); |
| |
| var server = new ScheduledServer(); |
| var pub = startPublish(server, args: ['--dry-run']); |
| |
| pub.shouldExit(0); |
| expect(pub.remainingStderr(), |
| completion(contains('Package has 0 warnings.'))); |
| }); |
| |
| integration('package validation has a warning and is canceled', () { |
| var pkg = packageMap("test_pkg", "1.0.0"); |
| pkg["author"] = "Nathan Weizenbaum"; |
| d.dir(appPath, [d.pubspec(pkg)]).create(); |
| |
| var server = new ScheduledServer(); |
| var pub = startPublish(server); |
| |
| pub.writeLine("n"); |
| pub.shouldExit(0); |
| expect(pub.remainingStderr(), |
| completion(contains("Package upload canceled."))); |
| }); |
| |
| integration('package validation has a warning and continues', () { |
| var pkg = packageMap("test_pkg", "1.0.0"); |
| pkg["author"] = "Nathan Weizenbaum"; |
| d.dir(appPath, [d.pubspec(pkg)]).create(); |
| |
| var server = new ScheduledServer(); |
| d.credentialsFile(server, 'access token').create(); |
| var pub = startPublish(server); |
| pub.writeLine("y"); |
| handleUploadForm(server); |
| handleUpload(server); |
| |
| server.handle('GET', '/create', (request) { |
| request.response.write(json.stringify({ |
| 'success': {'message': 'Package test_pkg 1.0.0 uploaded!'} |
| })); |
| request.response.close(); |
| }); |
| |
| pub.shouldExit(0); |
| expect(pub.remainingStdout(), |
| completion(contains('Package test_pkg 1.0.0 uploaded!'))); |
| }); |
| |
| integration('upload form provides an error', () { |
| var server = new ScheduledServer(); |
| d.credentialsFile(server, 'access token').create(); |
| var pub = startPublish(server); |
| |
| confirmPublish(pub); |
| |
| server.handle('GET', '/packages/versions/new.json', (request) { |
| request.response.statusCode = 400; |
| request.response.write(json.stringify({ |
| 'error': {'message': 'your request sucked'} |
| })); |
| request.response.close(); |
| }); |
| |
| expect(pub.nextErrLine(), completion(equals('your request sucked'))); |
| pub.shouldExit(1); |
| }); |
| |
| integration('upload form provides invalid JSON', () { |
| var server = new ScheduledServer(); |
| d.credentialsFile(server, 'access token').create(); |
| var pub = startPublish(server); |
| |
| confirmPublish(pub); |
| |
| server.handle('GET', '/packages/versions/new.json', (request) { |
| request.response.write('{not json'); |
| request.response.close(); |
| }); |
| |
| expect(pub.nextErrLine(), completion(equals('Invalid server response:'))); |
| expect(pub.nextErrLine(), completion(equals('{not json'))); |
| pub.shouldExit(1); |
| }); |
| |
| integration('upload form is missing url', () { |
| var server = new ScheduledServer(); |
| d.credentialsFile(server, 'access token').create(); |
| var pub = startPublish(server); |
| |
| confirmPublish(pub); |
| |
| var body = { |
| 'fields': { |
| 'field1': 'value1', |
| 'field2': 'value2' |
| } |
| }; |
| |
| handleUploadForm(server, body); |
| expect(pub.nextErrLine(), completion(equals('Invalid server response:'))); |
| expect(pub.nextErrLine(), completion(equals(json.stringify(body)))); |
| pub.shouldExit(1); |
| }); |
| |
| integration('upload form url is not a string', () { |
| var server = new ScheduledServer(); |
| d.credentialsFile(server, 'access token').create(); |
| var pub = startPublish(server); |
| |
| confirmPublish(pub); |
| |
| var body = { |
| 'url': 12, |
| 'fields': { |
| 'field1': 'value1', |
| 'field2': 'value2' |
| } |
| }; |
| |
| handleUploadForm(server, body); |
| expect(pub.nextErrLine(), completion(equals('Invalid server response:'))); |
| expect(pub.nextErrLine(), completion(equals(json.stringify(body)))); |
| pub.shouldExit(1); |
| }); |
| |
| integration('upload form is missing fields', () { |
| var server = new ScheduledServer(); |
| d.credentialsFile(server, 'access token').create(); |
| var pub = startPublish(server); |
| |
| confirmPublish(pub); |
| |
| var body = {'url': 'http://example.com/upload'}; |
| handleUploadForm(server, body); |
| expect(pub.nextErrLine(), completion(equals('Invalid server response:'))); |
| expect(pub.nextErrLine(), completion(equals(json.stringify(body)))); |
| pub.shouldExit(1); |
| }); |
| |
| integration('upload form fields is not a map', () { |
| var server = new ScheduledServer(); |
| d.credentialsFile(server, 'access token').create(); |
| var pub = startPublish(server); |
| |
| confirmPublish(pub); |
| |
| var body = {'url': 'http://example.com/upload', 'fields': 12}; |
| handleUploadForm(server, body); |
| expect(pub.nextErrLine(), completion(equals('Invalid server response:'))); |
| expect(pub.nextErrLine(), completion(equals(json.stringify(body)))); |
| pub.shouldExit(1); |
| }); |
| |
| integration('upload form fields has a non-string value', () { |
| var server = new ScheduledServer(); |
| d.credentialsFile(server, 'access token').create(); |
| var pub = startPublish(server); |
| |
| confirmPublish(pub); |
| |
| var body = { |
| 'url': 'http://example.com/upload', |
| 'fields': {'field': 12} |
| }; |
| handleUploadForm(server, body); |
| expect(pub.nextErrLine(), completion(equals('Invalid server response:'))); |
| expect(pub.nextErrLine(), completion(equals(json.stringify(body)))); |
| pub.shouldExit(1); |
| }); |
| |
| integration('cloud storage upload provides an error', () { |
| var server = new ScheduledServer(); |
| d.credentialsFile(server, 'access token').create(); |
| var pub = startPublish(server); |
| |
| confirmPublish(pub); |
| handleUploadForm(server); |
| |
| server.handle('POST', '/upload', (request) { |
| return drainStream(request).then((_) { |
| request.response.statusCode = 400; |
| request.response.headers.contentType = |
| new ContentType('application', 'xml'); |
| request.response.write('<Error><Message>Your request sucked.' |
| '</Message></Error>'); |
| request.response.close(); |
| }); |
| }); |
| |
| // TODO(nweiz): This should use the server's error message once the client |
| // can parse the XML. |
| expect(pub.nextErrLine(), |
| completion(equals('Failed to upload the package.'))); |
| pub.shouldExit(1); |
| }); |
| |
| integration("cloud storage upload doesn't redirect", () { |
| var server = new ScheduledServer(); |
| d.credentialsFile(server, 'access token').create(); |
| var pub = startPublish(server); |
| |
| confirmPublish(pub); |
| handleUploadForm(server); |
| |
| server.handle('POST', '/upload', (request) { |
| return drainStream(request).then((_) { |
| // Don't set the location header. |
| request.response.close(); |
| }); |
| }); |
| |
| expect(pub.nextErrLine(), |
| completion(equals('Failed to upload the package.'))); |
| pub.shouldExit(1); |
| }); |
| |
| integration('package creation provides an error', () { |
| var server = new ScheduledServer(); |
| d.credentialsFile(server, 'access token').create(); |
| var pub = startPublish(server); |
| |
| confirmPublish(pub); |
| handleUploadForm(server); |
| handleUpload(server); |
| |
| server.handle('GET', '/create', (request) { |
| request.response.statusCode = 400; |
| request.response.write(json.stringify({ |
| 'error': {'message': 'Your package was too boring.'} |
| })); |
| request.response.close(); |
| }); |
| |
| expect(pub.nextErrLine(), |
| completion(equals('Your package was too boring.'))); |
| pub.shouldExit(1); |
| }); |
| |
| integration('package creation provides invalid JSON', () { |
| var server = new ScheduledServer(); |
| d.credentialsFile(server, 'access token').create(); |
| var pub = startPublish(server); |
| |
| confirmPublish(pub); |
| handleUploadForm(server); |
| handleUpload(server); |
| |
| server.handle('GET', '/create', (request) { |
| request.response.write('{not json'); |
| request.response.close(); |
| }); |
| |
| expect(pub.nextErrLine(), completion(equals('Invalid server response:'))); |
| expect(pub.nextErrLine(), completion(equals('{not json'))); |
| pub.shouldExit(1); |
| }); |
| |
| integration('package creation provides a malformed error', () { |
| var server = new ScheduledServer(); |
| d.credentialsFile(server, 'access token').create(); |
| var pub = startPublish(server); |
| |
| confirmPublish(pub); |
| handleUploadForm(server); |
| handleUpload(server); |
| |
| var body = {'error': 'Your package was too boring.'}; |
| server.handle('GET', '/create', (request) { |
| request.response.statusCode = 400; |
| request.response.write(json.stringify(body)); |
| request.response.close(); |
| }); |
| |
| expect(pub.nextErrLine(), completion(equals('Invalid server response:'))); |
| expect(pub.nextErrLine(), completion(equals(json.stringify(body)))); |
| pub.shouldExit(1); |
| }); |
| |
| integration('package creation provides a malformed success', () { |
| var server = new ScheduledServer(); |
| d.credentialsFile(server, 'access token').create(); |
| var pub = startPublish(server); |
| |
| confirmPublish(pub); |
| handleUploadForm(server); |
| handleUpload(server); |
| |
| var body = {'success': 'Your package was awesome.'}; |
| server.handle('GET', '/create', (request) { |
| request.response.write(json.stringify(body)); |
| request.response.close(); |
| }); |
| |
| expect(pub.nextErrLine(), completion(equals('Invalid server response:'))); |
| expect(pub.nextErrLine(), completion(equals(json.stringify(body)))); |
| pub.shouldExit(1); |
| }); |
| |
| group('--force', () { |
| setUp(() => d.validPackage.create()); |
| |
| integration('cannot be combined with --dry-run', () { |
| schedulePub(args: ['lish', '--force', '--dry-run'], |
| error: "Cannot use both --force and --dry-run.", |
| exitCode: exit_codes.USAGE); |
| }); |
| |
| integration('publishes if there are no warnings or errors', () { |
| var server = new ScheduledServer(); |
| d.credentialsFile(server, 'access token').create(); |
| var pub = startPublish(server, args: ['--force']); |
| |
| handleUploadForm(server); |
| handleUpload(server); |
| |
| server.handle('GET', '/create', (request) { |
| request.response.write(json.stringify({ |
| 'success': {'message': 'Package test_pkg 1.0.0 uploaded!'} |
| })); |
| request.response.close(); |
| }); |
| |
| pub.shouldExit(0); |
| expect(pub.remainingStdout(), completion(contains( |
| 'Package test_pkg 1.0.0 uploaded!'))); |
| }); |
| |
| integration('publishes if there are warnings', () { |
| var pkg = packageMap("test_pkg", "1.0.0"); |
| pkg["author"] = "Nathan Weizenbaum"; |
| d.dir(appPath, [d.pubspec(pkg)]).create(); |
| |
| var server = new ScheduledServer(); |
| d.credentialsFile(server, 'access token').create(); |
| var pub = startPublish(server, args: ['--force']); |
| |
| handleUploadForm(server); |
| handleUpload(server); |
| |
| server.handle('GET', '/create', (request) { |
| request.response.write(json.stringify({ |
| 'success': {'message': 'Package test_pkg 1.0.0 uploaded!'} |
| })); |
| request.response.close(); |
| }); |
| |
| pub.shouldExit(0); |
| expect(pub.remainingStderr(), completion(contains( |
| 'Suggestions:\n* Author "Nathan Weizenbaum" in pubspec.yaml' |
| ' should have an email address\n' |
| ' (e.g. "name <email>").'))); |
| expect(pub.remainingStdout(), completion(contains( |
| 'Package test_pkg 1.0.0 uploaded!'))); |
| }); |
| |
| integration('does not publish if there are errors', () { |
| var pkg = packageMap("test_pkg", "1.0.0"); |
| pkg.remove("homepage"); |
| d.dir(appPath, [d.pubspec(pkg)]).create(); |
| |
| var server = new ScheduledServer(); |
| var pub = startPublish(server, args: ['--force']); |
| |
| pub.shouldExit(0); |
| expect(pub.remainingStderr(), completion(contains( |
| "Sorry, your package is missing a requirement and can't be " |
| "published yet."))); |
| }); |
| }); |
| } |