diff --git a/README.md b/README.md index d2b6971..e8b0729 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![pub package](https://img.shields.io/pub/v/appwrite?style=flat-square)](https://pub.dartlang.org/packages/appwrite) ![License](https://img.shields.io/github/license/appwrite/sdk-for-flutter.svg?style=flat-square) -![Version](https://img.shields.io/badge/api%20version-1.5.x-blue.svg?style=flat-square) +![Version](https://img.shields.io/badge/api%20version-1.6.x-blue.svg?style=flat-square) [![Build Status](https://img.shields.io/travis/com/appwrite/sdk-generator?style=flat-square)](https://travis-ci.com/appwrite/sdk-generator) [![Twitter Account](https://img.shields.io/twitter/follow/appwrite?color=00acee&label=twitter&style=flat-square)](https://twitter.com/appwrite) [![Discord](https://img.shields.io/discord/564160730845151244?label=discord&style=flat-square)](https://appwrite.io/discord) @@ -21,7 +21,7 @@ Add this to your package's `pubspec.yaml` file: ```yml dependencies: - appwrite: ^13.0.0-rc.1 + appwrite: ^13.0.0-rc.2 ``` You can install packages from the command line: diff --git a/docs/examples/account/delete-mfa-authenticator.md b/docs/examples/account/delete-mfa-authenticator.md index bc1cde4..66a0e89 100644 --- a/docs/examples/account/delete-mfa-authenticator.md +++ b/docs/examples/account/delete-mfa-authenticator.md @@ -8,5 +8,4 @@ Account account = Account(client); await account.deleteMfaAuthenticator( type: AuthenticatorType.totp, - otp: '', ); diff --git a/docs/examples/functions/get-deployment-download.md b/docs/examples/functions/get-deployment-download.md new file mode 100644 index 0000000..c6bda7d --- /dev/null +++ b/docs/examples/functions/get-deployment-download.md @@ -0,0 +1,29 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +Functions functions = Functions(client); + +// Downloading file +UInt8List bytes = await functions.getDeploymentDownload( + functionId: '', + deploymentId: '', +) + +final file = File('path_to_file/filename.ext'); +file.writeAsBytesSync(bytes); + +// Displaying image preview +FutureBuilder( + future: functions.getDeploymentDownload( + functionId:'' , + deploymentId:'' , +), // Works for both public file and private file, for private files you need to be logged in + builder: (context, snapshot) { + return snapshot.hasData && snapshot.data != null + ? Image.memory(snapshot.data) + : CircularProgressIndicator(); + } +); diff --git a/docs/examples/functions/get-template.md b/docs/examples/functions/get-template.md new file mode 100644 index 0000000..f08ec61 --- /dev/null +++ b/docs/examples/functions/get-template.md @@ -0,0 +1,11 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +Functions functions = Functions(client); + +TemplateFunction result = await functions.getTemplate( + templateId: '', +); diff --git a/docs/examples/functions/list-templates.md b/docs/examples/functions/list-templates.md new file mode 100644 index 0000000..bb14efc --- /dev/null +++ b/docs/examples/functions/list-templates.md @@ -0,0 +1,14 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +Functions functions = Functions(client); + +TemplateFunctionList result = await functions.listTemplates( + runtimes: [], // optional + useCases: [], // optional + limit: 1, // optional + offset: 0, // optional +); diff --git a/lib/appwrite.dart b/lib/appwrite.dart index 340c6b7..d0c2331 100644 --- a/lib/appwrite.dart +++ b/lib/appwrite.dart @@ -1,6 +1,6 @@ /// Appwrite Flutter SDK /// -/// This SDK is compatible with Appwrite server version 1.5.x. +/// This SDK is compatible with Appwrite server version 1.6.x. /// For older versions, please check /// [previous releases](https://github.com/appwrite/sdk-for-flutter/releases). library appwrite; diff --git a/lib/models.dart b/lib/models.dart index a6de0d8..df2bb3f 100644 --- a/lib/models.dart +++ b/lib/models.dart @@ -9,6 +9,7 @@ part 'src/models/log_list.dart'; part 'src/models/file_list.dart'; part 'src/models/team_list.dart'; part 'src/models/membership_list.dart'; +part 'src/models/template_function_list.dart'; part 'src/models/execution_list.dart'; part 'src/models/country_list.dart'; part 'src/models/continent_list.dart'; @@ -36,6 +37,9 @@ part 'src/models/locale_code.dart'; part 'src/models/file.dart'; part 'src/models/team.dart'; part 'src/models/membership.dart'; +part 'src/models/template_function.dart'; +part 'src/models/template_runtime.dart'; +part 'src/models/template_variable.dart'; part 'src/models/execution.dart'; part 'src/models/country.dart'; part 'src/models/continent.dart'; diff --git a/lib/services/account.dart b/lib/services/account.dart index 6e1304d..92803ae 100644 --- a/lib/services/account.dart +++ b/lib/services/account.dart @@ -184,7 +184,7 @@ class Account extends Service { } - /// Add Authenticator + /// Create Authenticator /// /// Add an authenticator app to be used as an MFA factor. Verify the /// authenticator using the [verify @@ -231,11 +231,10 @@ class Account extends Service { /// Delete Authenticator /// /// Delete an authenticator for a user by ID. - Future deleteMfaAuthenticator({required enums.AuthenticatorType type, required String otp}) async { + Future deleteMfaAuthenticator({required enums.AuthenticatorType type}) async { final String apiPath = '/account/mfa/authenticators/{type}'.replaceAll('{type}', type.value); final Map apiParams = { - 'otp': otp, }; final Map apiHeaders = { @@ -248,7 +247,7 @@ class Account extends Service { } - /// Create 2FA Challenge + /// Create MFA Challenge /// /// Begin the process of MFA verification after sign-in. Finish the flow with /// [updateMfaChallenge](/docs/references/cloud/client-web/account#updateMfaChallenge) @@ -1139,7 +1138,7 @@ class Account extends Service { } - /// Create phone verification (confirmation) + /// Update phone verification (confirmation) /// /// Use this endpoint to complete the user phone verification process. Use the /// **userId** and **secret** that were sent to your user's phone number to diff --git a/lib/services/avatars.dart b/lib/services/avatars.dart index 8eb0bb8..144c32a 100644 --- a/lib/services/avatars.dart +++ b/lib/services/avatars.dart @@ -66,6 +66,7 @@ class Avatars extends Service { /// Use this endpoint to fetch the favorite icon (AKA favicon) of any remote /// website URL. /// + /// This endpoint does not follow HTTP redirects. Future getFavicon({required String url}) async { const String apiPath = '/avatars/favicon'; @@ -120,6 +121,7 @@ class Avatars extends Service { /// image at source quality. If dimensions are not specified, the default size /// of image returned is 400x400px. /// + /// This endpoint does not follow HTTP redirects. Future getImage({required String url, int? width, int? height}) async { const String apiPath = '/avatars/image'; diff --git a/lib/services/functions.dart b/lib/services/functions.dart index 4ddd6df..ccaa6f6 100644 --- a/lib/services/functions.dart +++ b/lib/services/functions.dart @@ -6,6 +6,69 @@ class Functions extends Service { /// Initializes a [Functions] service Functions(super.client); + /// List function templates + /// + /// List available function templates. You can use template details in + /// [createFunction](/docs/references/cloud/server-nodejs/functions#create) + /// method. + Future listTemplates({List? runtimes, List? useCases, int? limit, int? offset}) async { + const String apiPath = '/functions/templates'; + + final Map apiParams = { + 'runtimes': runtimes, + 'useCases': useCases, + 'limit': limit, + 'offset': offset, + }; + + final Map apiHeaders = { + 'content-type': 'application/json', + }; + + final res = await client.call(HttpMethod.get, path: apiPath, params: apiParams, headers: apiHeaders); + + return models.TemplateFunctionList.fromMap(res.data); + + } + + /// Get function template + /// + /// Get a function template using ID. You can use template details in + /// [createFunction](/docs/references/cloud/server-nodejs/functions#create) + /// method. + Future getTemplate({required String templateId}) async { + final String apiPath = '/functions/templates/{templateId}'.replaceAll('{templateId}', templateId); + + final Map apiParams = { + }; + + final Map apiHeaders = { + 'content-type': 'application/json', + }; + + final res = await client.call(HttpMethod.get, path: apiPath, params: apiParams, headers: apiHeaders); + + return models.TemplateFunction.fromMap(res.data); + + } + + /// Download deployment + /// + /// Get a Deployment's contents by its unique ID. This endpoint supports range + /// requests for partial or streaming file download. + Future getDeploymentDownload({required String functionId, required String deploymentId}) async { + final String apiPath = '/functions/{functionId}/deployments/{deploymentId}/download'.replaceAll('{functionId}', functionId).replaceAll('{deploymentId}', deploymentId); + + final Map params = { + + + 'project': client.config['project'], + }; + + final res = await client.call(HttpMethod.get, path: apiPath, params: params, responseType: ResponseType.bytes); + return res.data; + } + /// List executions /// /// Get a list of all the current user function execution logs. You can use the @@ -34,10 +97,12 @@ class Functions extends Service { /// current execution status. You can ping the `Get Execution` endpoint to get /// updates on the current execution status. Once this endpoint is called, your /// function execution process will start asynchronously. - Future createExecution({required String functionId, String? body, bool? xasync, String? path, enums.ExecutionMethod? method, Map? headers, String? scheduledAt}) async { + Future createExecution({required String functionId, String? body, bool? xasync, String? path, enums.ExecutionMethod? method, Map? headers, String? scheduledAt, Function(UploadProgress)? onProgress}) async { final String apiPath = '/functions/{functionId}/executions'.replaceAll('{functionId}', functionId); final Map apiParams = { + + 'body': body, 'async': xasync, 'path': path, @@ -47,10 +112,18 @@ class Functions extends Service { }; final Map apiHeaders = { - 'content-type': 'application/json', + 'content-type': 'multipart/form-data', }; - final res = await client.call(HttpMethod.post, path: apiPath, params: apiParams, headers: apiHeaders); + String idParamName = ''; + final res = await client.chunkedUpload( + path: apiPath, + params: apiParams, + paramName: paramName, + idParamName: idParamName, + headers: apiHeaders, + onProgress: onProgress, + ); return models.Execution.fromMap(res.data); diff --git a/lib/src/client.dart b/lib/src/client.dart index 5201aed..825e24a 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -1,6 +1,6 @@ import 'enums.dart'; import 'client_stub.dart' - if (dart.library.html) 'client_browser.dart' + if (dart.library.js_interop) 'client_browser.dart' if (dart.library.io) 'client_io.dart'; import 'response.dart'; import 'upload_progress.dart'; diff --git a/lib/src/client_browser.dart b/lib/src/client_browser.dart index 6599822..d5648d3 100644 --- a/lib/src/client_browser.dart +++ b/lib/src/client_browser.dart @@ -3,7 +3,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter_web_auth_2/flutter_web_auth_2.dart'; import 'package:http/http.dart' as http; import 'package:http/browser_client.dart'; -import 'package:universal_html/html.dart' as html; +import 'package:web/web.dart' as web; import 'client_mixin.dart'; import 'enums.dart'; import 'exception.dart'; @@ -43,8 +43,8 @@ class ClientBrowser extends ClientBase with ClientMixin { 'x-sdk-name': 'Flutter', 'x-sdk-platform': 'client', 'x-sdk-language': 'flutter', - 'x-sdk-version': '13.0.0-rc.1', - 'X-Appwrite-Response-Format': '1.5.0', + 'x-sdk-version': '13.0.0-rc.2', + 'X-Appwrite-Response-Format': '1.6.0', }; config = {}; @@ -113,9 +113,9 @@ class ClientBrowser extends ClientBase with ClientMixin { } Future init() async { - if (html.window.localStorage.keys.contains('cookieFallback')) { - addHeader('x-fallback-cookies', - html.window.localStorage['cookieFallback'] ?? ''); + final cookieFallback = web.window.localStorage['cookieFallback']; + if (cookieFallback != null) { + addHeader('x-fallback-cookies', cookieFallback); } _httpClient.withCredentials = true; } @@ -213,7 +213,7 @@ class ClientBrowser extends ClientBase with ClientMixin { debugPrint( 'Appwrite is using localStorage for session management. Increase your security by adding a custom domain as your API endpoint.'); addHeader('X-Fallback-Cookies', cookieFallback); - html.window.localStorage['cookieFallback'] = cookieFallback; + web.window.localStorage['cookieFallback'] = cookieFallback; } return prepareResponse(res, responseType: responseType); } catch (e) { diff --git a/lib/src/client_io.dart b/lib/src/client_io.dart index 5a80ecc..f724282 100644 --- a/lib/src/client_io.dart +++ b/lib/src/client_io.dart @@ -64,8 +64,8 @@ class ClientIO extends ClientBase with ClientMixin { 'x-sdk-name': 'Flutter', 'x-sdk-platform': 'client', 'x-sdk-language': 'flutter', - 'x-sdk-version': '13.0.0-rc.1', - 'X-Appwrite-Response-Format' : '1.5.0', + 'x-sdk-version': '13.0.0-rc.2', + 'X-Appwrite-Response-Format' : '1.6.0', }; config = {}; diff --git a/lib/src/models/execution.dart b/lib/src/models/execution.dart index d56dc16..96548ef 100644 --- a/lib/src/models/execution.dart +++ b/lib/src/models/execution.dart @@ -34,6 +34,8 @@ class Execution implements Model { final String errors; /// Function execution duration in seconds. final double duration; + /// The scheduled time for execution. If left empty, execution will be queued immediately. + final String? scheduledAt; Execution({ required this.$id, @@ -52,6 +54,7 @@ class Execution implements Model { required this.logs, required this.errors, required this.duration, + this.scheduledAt, }); factory Execution.fromMap(Map map) { @@ -72,6 +75,7 @@ class Execution implements Model { logs: map['logs'].toString(), errors: map['errors'].toString(), duration: map['duration'].toDouble(), + scheduledAt: map['scheduledAt']?.toString(), ); } @@ -93,6 +97,7 @@ class Execution implements Model { "logs": logs, "errors": errors, "duration": duration, + "scheduledAt": scheduledAt, }; } } diff --git a/lib/src/models/template_function.dart b/lib/src/models/template_function.dart new file mode 100644 index 0000000..c3fcbe4 --- /dev/null +++ b/lib/src/models/template_function.dart @@ -0,0 +1,103 @@ +part of '../../models.dart'; + +/// Template Function +class TemplateFunction implements Model { + /// Function Template Icon. + final String icon; + /// Function Template ID. + final String id; + /// Function Template Name. + final String name; + /// Function Template Tagline. + final String tagline; + /// Execution permissions. + final List permissions; + /// Function trigger events. + final List events; + /// Function execution schedult in CRON format. + final String cron; + /// Function execution timeout in seconds. + final int timeout; + /// Function use cases. + final List useCases; + /// List of runtimes that can be used with this template. + final List runtimes; + /// Function Template Instructions. + final String instructions; + /// VCS (Version Control System) Provider. + final String vcsProvider; + /// VCS (Version Control System) Repository ID + final String providerRepositoryId; + /// VCS (Version Control System) Owner. + final String providerOwner; + /// VCS (Version Control System) branch version (tag). + final String providerVersion; + /// Function variables. + final List variables; + /// Function scopes. + final List scopes; + + TemplateFunction({ + required this.icon, + required this.id, + required this.name, + required this.tagline, + required this.permissions, + required this.events, + required this.cron, + required this.timeout, + required this.useCases, + required this.runtimes, + required this.instructions, + required this.vcsProvider, + required this.providerRepositoryId, + required this.providerOwner, + required this.providerVersion, + required this.variables, + required this.scopes, + }); + + factory TemplateFunction.fromMap(Map map) { + return TemplateFunction( + icon: map['icon'].toString(), + id: map['id'].toString(), + name: map['name'].toString(), + tagline: map['tagline'].toString(), + permissions: map['permissions'] ?? [], + events: map['events'] ?? [], + cron: map['cron'].toString(), + timeout: map['timeout'], + useCases: map['useCases'] ?? [], + runtimes: List.from(map['runtimes'].map((p) => TemplateRuntime.fromMap(p))), + instructions: map['instructions'].toString(), + vcsProvider: map['vcsProvider'].toString(), + providerRepositoryId: map['providerRepositoryId'].toString(), + providerOwner: map['providerOwner'].toString(), + providerVersion: map['providerVersion'].toString(), + variables: List.from(map['variables'].map((p) => TemplateVariable.fromMap(p))), + scopes: map['scopes'] ?? [], + ); + } + + Map toMap() { + return { + "icon": icon, + "id": id, + "name": name, + "tagline": tagline, + "permissions": permissions, + "events": events, + "cron": cron, + "timeout": timeout, + "useCases": useCases, + "runtimes": runtimes.map((p) => p.toMap()).toList(), + "instructions": instructions, + "vcsProvider": vcsProvider, + "providerRepositoryId": providerRepositoryId, + "providerOwner": providerOwner, + "providerVersion": providerVersion, + "variables": variables.map((p) => p.toMap()).toList(), + "scopes": scopes, + }; + } +} diff --git a/lib/src/models/template_function_list.dart b/lib/src/models/template_function_list.dart new file mode 100644 index 0000000..dddb2c9 --- /dev/null +++ b/lib/src/models/template_function_list.dart @@ -0,0 +1,28 @@ +part of '../../models.dart'; + +/// Function Templates List +class TemplateFunctionList implements Model { + /// Total number of templates documents that matched your query. + final int total; + /// List of templates. + final List templates; + + TemplateFunctionList({ + required this.total, + required this.templates, + }); + + factory TemplateFunctionList.fromMap(Map map) { + return TemplateFunctionList( + total: map['total'], + templates: List.from(map['templates'].map((p) => TemplateFunction.fromMap(p))), + ); + } + + Map toMap() { + return { + "total": total, + "templates": templates.map((p) => p.toMap()).toList(), + }; + } +} diff --git a/lib/src/models/template_runtime.dart b/lib/src/models/template_runtime.dart new file mode 100644 index 0000000..34209d1 --- /dev/null +++ b/lib/src/models/template_runtime.dart @@ -0,0 +1,38 @@ +part of '../../models.dart'; + +/// Template Runtime +class TemplateRuntime implements Model { + /// Runtime Name. + final String name; + /// The build command used to build the deployment. + final String commands; + /// The entrypoint file used to execute the deployment. + final String entrypoint; + /// Path to function in VCS (Version Control System) repository + final String providerRootDirectory; + + TemplateRuntime({ + required this.name, + required this.commands, + required this.entrypoint, + required this.providerRootDirectory, + }); + + factory TemplateRuntime.fromMap(Map map) { + return TemplateRuntime( + name: map['name'].toString(), + commands: map['commands'].toString(), + entrypoint: map['entrypoint'].toString(), + providerRootDirectory: map['providerRootDirectory'].toString(), + ); + } + + Map toMap() { + return { + "name": name, + "commands": commands, + "entrypoint": entrypoint, + "providerRootDirectory": providerRootDirectory, + }; + } +} diff --git a/lib/src/models/template_variable.dart b/lib/src/models/template_variable.dart new file mode 100644 index 0000000..df3982c --- /dev/null +++ b/lib/src/models/template_variable.dart @@ -0,0 +1,48 @@ +part of '../../models.dart'; + +/// Template Variable +class TemplateVariable implements Model { + /// Variable Name. + final String name; + /// Variable Description. + final String description; + /// Variable Value. + final String value; + /// Variable Placeholder. + final String placeholder; + /// Is the variable required? + final bool xrequired; + /// Variable Type. + final String type; + + TemplateVariable({ + required this.name, + required this.description, + required this.value, + required this.placeholder, + required this.xrequired, + required this.type, + }); + + factory TemplateVariable.fromMap(Map map) { + return TemplateVariable( + name: map['name'].toString(), + description: map['description'].toString(), + value: map['value'].toString(), + placeholder: map['placeholder'].toString(), + xrequired: map['required'], + type: map['type'].toString(), + ); + } + + Map toMap() { + return { + "name": name, + "description": description, + "value": value, + "placeholder": placeholder, + "required": xrequired, + "type": type, + }; + } +} diff --git a/lib/src/realtime.dart b/lib/src/realtime.dart index fffb7c6..e02d89a 100644 --- a/lib/src/realtime.dart +++ b/lib/src/realtime.dart @@ -1,5 +1,5 @@ import 'realtime_stub.dart' - if (dart.library.html) 'realtime_browser.dart' + if (dart.library.js_interop) 'realtime_browser.dart' if (dart.library.io) 'realtime_io.dart'; import 'realtime_subscription.dart'; import 'service.dart'; diff --git a/lib/src/realtime_browser.dart b/lib/src/realtime_browser.dart index 1567f64..8e56103 100644 --- a/lib/src/realtime_browser.dart +++ b/lib/src/realtime_browser.dart @@ -1,6 +1,6 @@ import 'dart:convert'; import 'dart:async'; -import 'package:universal_html/html.dart' as html; +import 'package:web/web.dart' as web; import 'package:web_socket_channel/html.dart'; import 'package:web_socket_channel/web_socket_channel.dart'; import 'realtime_subscription.dart'; @@ -26,7 +26,7 @@ class RealtimeBrowser extends RealtimeBase with RealtimeMixin { } String? _getFallbackCookie() { - final fallbackCookie = html.window.localStorage['cookieFallback']; + final fallbackCookie = web.window.localStorage['cookieFallback']; if (fallbackCookie != null) { final cookie = Map.from(jsonDecode(fallbackCookie)); return cookie.values.first; diff --git a/pubspec.yaml b/pubspec.yaml index 887565d..5cb048f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: appwrite -version: 13.0.0-rc.1 +version: 13.0.0-rc.2 description: Appwrite is an open-source self-hosted backend server that abstract and simplify complex and repetitive development tasks behind a very simple REST API homepage: https://appwrite.io repository: https://github.com/appwrite/sdk-for-flutter @@ -20,16 +20,16 @@ dependencies: sdk: flutter cookie_jar: ^4.0.8 device_info_plus: ^10.1.0 - flutter_web_auth_2: ^3.1.1 + flutter_web_auth_2: ^3.1.2 http: '>=0.13.6 <2.0.0' package_info_plus: ^8.0.0 path_provider: ^2.1.3 - web_socket_channel: ^2.4.5 - universal_html: ^2.2.4 + web_socket_channel: ^3.0.0 + web: ^0.5.1 dev_dependencies: path_provider_platform_interface: ^2.1.2 - flutter_lints: ^3.0.2 + flutter_lints: ^4.0.0 flutter_test: sdk: flutter mockito: ^5.4.4 diff --git a/test/services/account_test.dart b/test/services/account_test.dart index d7bf0fb..3f76e30 100644 --- a/test/services/account_test.dart +++ b/test/services/account_test.dart @@ -308,7 +308,6 @@ void main() { final response = await account.deleteMfaAuthenticator( type: 'totp', - otp: '', ); }); diff --git a/test/services/functions_test.dart b/test/services/functions_test.dart index 8707d05..96a8736 100644 --- a/test/services/functions_test.dart +++ b/test/services/functions_test.dart @@ -54,6 +54,71 @@ void main() { functions = Functions(client); }); + test('test method listTemplates()', () async { + final Map data = { + 'total': 5, + 'templates': [],}; + + + when(client.call( + HttpMethod.get, + )).thenAnswer((_) async => Response(data: data)); + + + final response = await functions.listTemplates( + ); + expect(response, isA()); + + }); + + test('test method getTemplate()', () async { + final Map data = { + 'icon': 'icon-lightning-bolt', + 'id': 'starter', + 'name': 'Starter function', + 'tagline': 'A simple function to get started.', + 'permissions': [], + 'events': [], + 'cron': '0 0 * * *', + 'timeout': 300, + 'useCases': [], + 'runtimes': [], + 'instructions': 'For documentation and instructions check out .', + 'vcsProvider': 'github', + 'providerRepositoryId': 'templates', + 'providerOwner': 'appwrite', + 'providerVersion': 'main', + 'variables': [], + 'scopes': [],}; + + + when(client.call( + HttpMethod.get, + )).thenAnswer((_) async => Response(data: data)); + + + final response = await functions.getTemplate( + templateId: '', + ); + expect(response, isA()); + + }); + + test('test method getDeploymentDownload()', () async {final Uint8List data = Uint8List.fromList([]); + + when(client.call( + HttpMethod.get, + )).thenAnswer((_) async => Response(data: data)); + + + final response = await functions.getDeploymentDownload( + functionId: '', + deploymentId: '', + ); + expect(response, isA()); + + }); + test('test method listExecutions()', () async { final Map data = { 'total': 5, @@ -92,8 +157,12 @@ void main() { 'duration': 0.4,}; - when(client.call( - HttpMethod.post, + when(client.chunkedUpload( + path: argThat(isNotNull), + params: argThat(isNotNull), + paramName: argThat(isNotNull), + idParamName: argThat(isNotNull), + headers: argThat(isNotNull), )).thenAnswer((_) async => Response(data: data)); diff --git a/test/src/models/template_function_list_test.dart b/test/src/models/template_function_list_test.dart new file mode 100644 index 0000000..98300b8 --- /dev/null +++ b/test/src/models/template_function_list_test.dart @@ -0,0 +1,20 @@ +import 'package:appwrite/models.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('TemplateFunctionList', () { + + test('model', () { + final model = TemplateFunctionList( + total: 5, + templates: [], + ); + + final map = model.toMap(); + final result = TemplateFunctionList.fromMap(map); + + expect(result.total, 5); + expect(result.templates, []); + }); + }); +} diff --git a/test/src/models/template_function_test.dart b/test/src/models/template_function_test.dart new file mode 100644 index 0000000..e1e94cf --- /dev/null +++ b/test/src/models/template_function_test.dart @@ -0,0 +1,50 @@ +import 'package:appwrite/models.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('TemplateFunction', () { + + test('model', () { + final model = TemplateFunction( + icon: 'icon-lightning-bolt', + id: 'starter', + name: 'Starter function', + tagline: 'A simple function to get started.', + permissions: [], + events: [], + cron: '0 0 * * *', + timeout: 300, + useCases: [], + runtimes: [], + instructions: 'For documentation and instructions check out .', + vcsProvider: 'github', + providerRepositoryId: 'templates', + providerOwner: 'appwrite', + providerVersion: 'main', + variables: [], + scopes: [], + ); + + final map = model.toMap(); + final result = TemplateFunction.fromMap(map); + + expect(result.icon, 'icon-lightning-bolt'); + expect(result.id, 'starter'); + expect(result.name, 'Starter function'); + expect(result.tagline, 'A simple function to get started.'); + expect(result.permissions, []); + expect(result.events, []); + expect(result.cron, '0 0 * * *'); + expect(result.timeout, 300); + expect(result.useCases, []); + expect(result.runtimes, []); + expect(result.instructions, 'For documentation and instructions check out .'); + expect(result.vcsProvider, 'github'); + expect(result.providerRepositoryId, 'templates'); + expect(result.providerOwner, 'appwrite'); + expect(result.providerVersion, 'main'); + expect(result.variables, []); + expect(result.scopes, []); + }); + }); +} diff --git a/test/src/models/template_runtime_test.dart b/test/src/models/template_runtime_test.dart new file mode 100644 index 0000000..cea1e41 --- /dev/null +++ b/test/src/models/template_runtime_test.dart @@ -0,0 +1,24 @@ +import 'package:appwrite/models.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('TemplateRuntime', () { + + test('model', () { + final model = TemplateRuntime( + name: 'node-19.0', + commands: 'npm install', + entrypoint: 'index.js', + providerRootDirectory: 'node/starter', + ); + + final map = model.toMap(); + final result = TemplateRuntime.fromMap(map); + + expect(result.name, 'node-19.0'); + expect(result.commands, 'npm install'); + expect(result.entrypoint, 'index.js'); + expect(result.providerRootDirectory, 'node/starter'); + }); + }); +} diff --git a/test/src/models/template_variable_test.dart b/test/src/models/template_variable_test.dart new file mode 100644 index 0000000..9da0fdf --- /dev/null +++ b/test/src/models/template_variable_test.dart @@ -0,0 +1,28 @@ +import 'package:appwrite/models.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('TemplateVariable', () { + + test('model', () { + final model = TemplateVariable( + name: 'APPWRITE_DATABASE_ID', + description: 'The ID of the Appwrite database that contains the collection to sync.', + value: '512', + placeholder: '64a55...7b912', + xrequired: true, + type: 'password', + ); + + final map = model.toMap(); + final result = TemplateVariable.fromMap(map); + + expect(result.name, 'APPWRITE_DATABASE_ID'); + expect(result.description, 'The ID of the Appwrite database that contains the collection to sync.'); + expect(result.value, '512'); + expect(result.placeholder, '64a55...7b912'); + expect(result.xrequired, true); + expect(result.type, 'password'); + }); + }); +}