Browse Source

fix: run bloc_test (#1286)

* fix: run bloc_test

* fix: dart_test ci  workflow

Co-authored-by: nathan <[email protected]>
Nathan.fooo 2 years ago
parent
commit
230eb5fd55

+ 1 - 1
.github/workflows/dart_test.yml

@@ -67,7 +67,7 @@ jobs:
       - name: Build FlowySDK
         working-directory: frontend
         run: |
-          cargo make --profile development-linux-x86_64 flowy-sdk-dev
+          cargo make --profile test-linux test-lib-build
 
       - name: Code Generation
         working-directory: frontend/app_flowy

+ 54 - 7
frontend/Makefile.toml

@@ -40,10 +40,15 @@ PRODUCT_NAME = "AppFlowy"
 #   for cdylib:
 #       if (Platform.isMacOS) return DynamicLibrary.open('${prefix}/libdart_ffi.dylib');
 CRATE_TYPE = "staticlib"
-SDK_EXT = "a"
+LIB_EXT = "a"
 APP_ENVIRONMENT = "local"
 FLUTTER_FLOWY_SDK_PATH = "app_flowy/packages/flowy_sdk"
 PROTOBUF_DERIVE_CACHE = "../shared-lib/flowy-derive/src/derive_cache/derive_cache.rs"
+# Test default config
+TEST_CRATE_TYPE = "cdylib"
+TEST_LIB_EXT = "dylib"
+TEST_BUILD_FLAG = "debug"
+TEST_COMPILE_TARGET = "x86_64-apple-darwin"
 
 [env.development-mac-arm64]
 RUST_LOG = "info"
@@ -88,7 +93,7 @@ BUILD_FLAG = "debug"
 FLUTTER_OUTPUT_DIR = "Debug"
 PRODUCT_EXT = "exe"
 CRATE_TYPE = "cdylib"
-SDK_EXT = "dll"
+LIB_EXT = "dll"
 
 [env.production-windows-x86]
 BUILD_FLAG = "release"
@@ -97,7 +102,7 @@ RUST_COMPILE_TARGET = "x86_64-pc-windows-msvc"
 FLUTTER_OUTPUT_DIR = "Release"
 PRODUCT_EXT = "exe"
 CRATE_TYPE = "cdylib"
-SDK_EXT = "dll"
+LIB_EXT = "dll"
 APP_ENVIRONMENT = "production"
 
 [env.development-linux-x86_64]
@@ -106,7 +111,7 @@ RUST_COMPILE_TARGET = "x86_64-unknown-linux-gnu"
 BUILD_FLAG = "debug"
 CRATE_TYPE = "cdylib"
 FLUTTER_OUTPUT_DIR = "Debug"
-SDK_EXT = "so"
+LIB_EXT = "so"
 LINUX_ARCH = "x64"
 
 [env.production-linux-x86_64]
@@ -115,7 +120,7 @@ TARGET_OS = "linux"
 RUST_COMPILE_TARGET = "x86_64-unknown-linux-gnu"
 CRATE_TYPE = "cdylib"
 FLUTTER_OUTPUT_DIR = "Release"
-SDK_EXT = "so"
+LIB_EXT = "so"
 LINUX_ARCH = "x64"
 APP_ENVIRONMENT = "production"
 
@@ -125,7 +130,7 @@ RUST_COMPILE_TARGET = "aarch64-unknown-linux-gnu"
 BUILD_FLAG = "debug"
 CRATE_TYPE = "cdylib"
 FLUTTER_OUTPUT_DIR = "Debug"
-SDK_EXT = "so"
+LIB_EXT = "so"
 LINUX_ARCH = "arm64"
 
 [env.production-linux-aarch64]
@@ -134,7 +139,7 @@ TARGET_OS = "linux"
 RUST_COMPILE_TARGET = "aarch64-unknown-linux-gnu"
 CRATE_TYPE = "cdylib"
 FLUTTER_OUTPUT_DIR = "Release"
-SDK_EXT = "so"
+LIB_EXT = "so"
 LINUX_ARCH = "arm64"
 APP_ENVIRONMENT = "production"
 
@@ -197,6 +202,46 @@ script = [
 ]
 script_runner = "@duckscript"
 
+[env.test-macos]
+TEST_CRATE_TYPE = "cdylib"
+TEST_LIB_EXT = "dylib"
+# For the moment, the DynamicLibrary only supports open x86_64 architectures binary.
+TEST_COMPILE_TARGET = "x86_64-apple-darwin"
+
+[env.test-linux]
+TEST_CRATE_TYPE = "cdylib"
+TEST_LIB_EXT = "so"
+TEST_COMPILE_TARGET = "x86_64-unknown-linux-gnu"
+
+[env.test-windows]
+TEST_CRATE_TYPE = "cdylib"
+TEST_LIB_EXT = "dll"
+TEST_COMPILE_TARGET = "x86_64-pc-windows-msvc"
+
+[tasks.setup-test-crate-type]
+private = true
+script = [
+    """
+      toml = readfile ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/Cargo.toml
+      val = replace ${toml} "staticlib" ${TEST_CRATE_TYPE}
+      result = writefile ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/Cargo.toml ${val}
+      assert ${result}
+      """,
+]
+script_runner = "@duckscript"
+
+[tasks.restore-test-crate-type]
+private = true
+script = [
+    """
+      toml = readfile ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/Cargo.toml
+      val = replace ${toml} ${TEST_CRATE_TYPE} "staticlib"
+      result = writefile ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/${CARGO_MAKE_CRATE_NAME}/Cargo.toml ${val}
+      assert ${result}
+      """,
+]
+script_runner = "@duckscript"
+
 [tasks.test-build]
 condition = { env_set = ["FLUTTER_FLOWY_SDK_PATH"] }
 script = ["""
@@ -204,3 +249,5 @@ script = ["""
       cargo build -vv --features=dart
       """]
 script_runner = "@shell"
+
+

+ 16 - 0
frontend/app_flowy/lib/plugins/board/tests/integrate_test/card_test.dart

@@ -0,0 +1,16 @@
+// import 'package:flutter_test/flutter_test.dart';
+// import 'package:integration_test/integration_test.dart';
+// import 'package:app_flowy/main.dart' as app;
+
+// void main() {
+//   IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+
+//   group('end-to-end test', () {
+//     testWidgets('tap on the floating action button, verify counter',
+//         (tester) async {
+//       app.main();
+
+//       await tester.pumpAndSettle();
+//     });
+//   });
+// }

+ 2 - 2
frontend/app_flowy/lib/startup/tasks/rust_sdk.dart

@@ -16,12 +16,12 @@ class InitRustSDKTask extends LaunchTask {
 }
 
 Future<Directory> appFlowyDocumentDirectory() async {
-  Directory documentsDir = await getApplicationDocumentsDirectory();
-
   switch (integrationEnv()) {
     case IntegrationMode.develop:
+      Directory documentsDir = await getApplicationDocumentsDirectory();
       return Directory('${documentsDir.path}/flowy_dev').create();
     case IntegrationMode.release:
+      Directory documentsDir = await getApplicationDocumentsDirectory();
       return Directory('${documentsDir.path}/flowy').create();
     case IntegrationMode.test:
       return Directory("${Directory.current.path}/.sandbox");

+ 12 - 11
frontend/app_flowy/packages/flowy_sdk/lib/ffi.dart

@@ -7,10 +7,10 @@ import 'package:ffi/ffi.dart' as ffi;
 import 'package:flutter/foundation.dart' as Foundation;
 
 // ignore_for_file: unused_import, camel_case_types, non_constant_identifier_names
-final DynamicLibrary _dl = _open();
+final DynamicLibrary _dart_ffi_lib = _open();
 
 /// Reference to the Dynamic Library, it should be only used for low-level access
-final DynamicLibrary dl = _dl;
+final DynamicLibrary dl = _dart_ffi_lib;
 DynamicLibrary _open() {
   if (Platform.environment.containsKey('FLUTTER_TEST')) {
     final prefix = "${Directory.current.path}/.sandbox";
@@ -18,7 +18,8 @@ DynamicLibrary _open() {
       return DynamicLibrary.open('${prefix}/libdart_ffi.so');
     if (Platform.isAndroid)
       return DynamicLibrary.open('${prefix}/libdart_ffi.so');
-    if (Platform.isMacOS) return DynamicLibrary.open('${prefix}/libdart_ffi.a');
+    if (Platform.isMacOS)
+      return DynamicLibrary.open('${prefix}/libdart_ffi.dylib');
     if (Platform.isIOS) return DynamicLibrary.open('${prefix}/libdart_ffi.a');
     if (Platform.isWindows)
       return DynamicLibrary.open('${prefix}/dart_ffi.dll');
@@ -42,8 +43,8 @@ void async_event(
   _invoke_async(port, input, len);
 }
 
-final _invoke_async_Dart _invoke_async =
-    _dl.lookupFunction<_invoke_async_C, _invoke_async_Dart>('async_event');
+final _invoke_async_Dart _invoke_async = _dart_ffi_lib
+    .lookupFunction<_invoke_async_C, _invoke_async_Dart>('async_event');
 typedef _invoke_async_C = Void Function(
   Int64 port,
   Pointer<Uint8> input,
@@ -63,8 +64,8 @@ Pointer<Uint8> sync_event(
   return _invoke_sync(input, len);
 }
 
-final _invoke_sync_Dart _invoke_sync =
-    _dl.lookupFunction<_invoke_sync_C, _invoke_sync_Dart>('sync_event');
+final _invoke_sync_Dart _invoke_sync = _dart_ffi_lib
+    .lookupFunction<_invoke_sync_C, _invoke_sync_Dart>('sync_event');
 typedef _invoke_sync_C = Pointer<Uint8> Function(
   Pointer<Uint8> input,
   Uint64 len,
@@ -82,7 +83,7 @@ int init_sdk(
 }
 
 final _init_sdk_Dart _init_sdk =
-    _dl.lookupFunction<_init_sdk_C, _init_sdk_Dart>('init_sdk');
+    _dart_ffi_lib.lookupFunction<_init_sdk_C, _init_sdk_Dart>('init_sdk');
 typedef _init_sdk_C = Int64 Function(
   Pointer<ffi.Utf8> path,
 );
@@ -96,7 +97,7 @@ int set_stream_port(int port) {
 }
 
 final _set_stream_port_Dart _set_stream_port =
-    _dl.lookupFunction<_set_stream_port_C, _set_stream_port_Dart>(
+    _dart_ffi_lib.lookupFunction<_set_stream_port_C, _set_stream_port_Dart>(
         'set_stream_port');
 
 typedef _set_stream_port_C = Int32 Function(
@@ -111,7 +112,7 @@ void link_me_please() {
   _link_me_please();
 }
 
-final _link_me_please_Dart _link_me_please = _dl
+final _link_me_please_Dart _link_me_please = _dart_ffi_lib
     .lookupFunction<_link_me_please_C, _link_me_please_Dart>('link_me_please');
 typedef _link_me_please_C = Void Function();
 typedef _link_me_please_Dart = void Function();
@@ -123,7 +124,7 @@ void store_dart_post_cobject(
   _store_dart_post_cobject(ptr);
 }
 
-final _store_dart_post_cobject_Dart _store_dart_post_cobject = _dl
+final _store_dart_post_cobject_Dart _store_dart_post_cobject = _dart_ffi_lib
     .lookupFunction<_store_dart_post_cobject_C, _store_dart_post_cobject_Dart>(
         'store_dart_post_cobject');
 typedef _store_dart_post_cobject_C = Void Function(

+ 34 - 5
frontend/app_flowy/pubspec.lock

@@ -49,7 +49,7 @@ packages:
       name: archive
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "3.3.1"
+    version: "3.1.11"
   args:
     dependency: transitive
     description:
@@ -245,7 +245,7 @@ packages:
       name: coverage
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.3.2"
+    version: "1.2.0"
   cross_file:
     dependency: transitive
     description:
@@ -259,7 +259,7 @@ packages:
       name: crypto
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "3.0.2"
+    version: "3.0.1"
   csslib:
     dependency: transitive
     description:
@@ -454,6 +454,11 @@ packages:
       url: "https://pub.dartlang.org"
     source: hosted
     version: "0.6.1"
+  flutter_driver:
+    dependency: transitive
+    description: flutter
+    source: sdk
+    version: "0.0.0"
   flutter_inappwebview:
     dependency: transitive
     description:
@@ -555,6 +560,11 @@ packages:
       url: "https://pub.dartlang.org"
     source: hosted
     version: "2.1.3"
+  fuchsia_remote_debug_protocol:
+    dependency: transitive
+    description: flutter
+    source: sdk
+    version: "0.0.0"
   get_it:
     dependency: "direct main"
     description:
@@ -660,6 +670,11 @@ packages:
       url: "https://pub.dartlang.org"
     source: hosted
     version: "2.5.0"
+  integration_test:
+    dependency: "direct dev"
+    description: flutter
+    source: sdk
+    version: "0.0.0"
   intl:
     dependency: "direct main"
     description:
@@ -1246,6 +1261,13 @@ packages:
       url: "https://pub.dartlang.org"
     source: hosted
     version: "0.3.1+2"
+  sync_http:
+    dependency: transitive
+    description:
+      name: sync_http
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "0.3.0"
   table_calendar:
     dependency: "direct main"
     description:
@@ -1322,7 +1344,7 @@ packages:
       name: typed_data
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.3.1"
+    version: "1.3.0"
   universal_platform:
     dependency: transitive
     description:
@@ -1441,7 +1463,7 @@ packages:
       name: vm_service
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "8.3.0"
+    version: "8.2.2"
   watcher:
     dependency: transitive
     description:
@@ -1456,6 +1478,13 @@ packages:
       url: "https://pub.dartlang.org"
     source: hosted
     version: "2.2.0"
+  webdriver:
+    dependency: transitive
+    description:
+      name: webdriver
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "3.0.0"
   webkit_inspection_protocol:
     dependency: transitive
     description:

+ 2 - 0
frontend/app_flowy/pubspec.yaml

@@ -97,6 +97,8 @@ dev_dependencies:
 
   flutter_test:
     sdk: flutter
+  integration_test:
+    sdk: flutter
   build_runner: ^2.2.0
   freezed: ^2.1.0+1
   bloc_test: ^9.0.2

+ 3 - 3
frontend/app_flowy/test/workspace_bloc_test.dart → frontend/app_flowy/test/bloc_test/workspace_bloc_test.dart

@@ -4,13 +4,13 @@ import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
 import 'package:flutter_test/flutter_test.dart';
 import 'package:bloc_test/bloc_test.dart';
 
-import 'util/test_env.dart';
+import '../util.dart';
 
 void main() {
   UserProfilePB? userInfo;
   setUpAll(() async {
-    final flowyTest = await FlowyTest.setup();
-    userInfo = await flowyTest.signIn();
+    await AppFlowyBlocTest.ensureInitialized();
+    userInfo = await signIn();
   });
 
   group('WelcomeBloc', () {

+ 65 - 0
frontend/app_flowy/test/util.dart

@@ -0,0 +1,65 @@
+import 'package:app_flowy/startup/startup.dart';
+import 'package:app_flowy/user/application/auth_service.dart';
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flowy_infra/uuid.dart';
+import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:integration_test/integration_test.dart';
+import 'package:app_flowy/main.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+
+class AppFlowyIntegrateTest {
+  static Future<AppFlowyIntegrateTest> ensureInitialized() async {
+    IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+    SharedPreferences.setMockInitialValues({});
+    main();
+    return AppFlowyIntegrateTest();
+  }
+}
+
+class AppFlowyBlocTest {
+  static Future<AppFlowyBlocTest> ensureInitialized() async {
+    TestWidgetsFlutterBinding.ensureInitialized();
+    SharedPreferences.setMockInitialValues({});
+    pathProviderInitialized();
+
+    await EasyLocalization.ensureInitialized();
+    await FlowyRunner.run(FlowyTestApp());
+    return AppFlowyBlocTest();
+  }
+}
+
+void pathProviderInitialized() {
+  const MethodChannel channel =
+      MethodChannel('plugins.flutter.io/path_provider');
+  channel.setMockMethodCallHandler((MethodCall methodCall) async {
+    return ".";
+  });
+}
+
+Future<UserProfilePB> signIn() async {
+  final authService = getIt<AuthService>();
+  const password = "AppFlowy123@";
+  final uid = uuid();
+  final userEmail = "[email protected]";
+  final result = await authService.signUp(
+    name: "FlowyTestUser",
+    password: password,
+    email: userEmail,
+  );
+  return result.fold(
+    (user) => user,
+    (error) {
+      throw StateError("$error");
+    },
+  );
+}
+
+class FlowyTestApp implements EntryPoint {
+  @override
+  Widget create() {
+    return Container();
+  }
+}

+ 0 - 41
frontend/app_flowy/test/util/test_env.dart

@@ -1,41 +0,0 @@
-import 'package:app_flowy/startup/startup.dart';
-import 'package:app_flowy/user/application/auth_service.dart';
-import 'package:flowy_infra/uuid.dart';
-import 'package:flowy_sdk/protobuf/flowy-user/protobuf.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_test/flutter_test.dart';
-
-class FlowyTest {
-  static Future<FlowyTest> setup() async {
-    TestWidgetsFlutterBinding.ensureInitialized();
-    // await EasyLocalization.ensureInitialized();
-
-    await FlowyRunner.run(FlowyTestApp());
-    return FlowyTest();
-  }
-
-  Future<UserProfilePB> signIn() async {
-    final authService = getIt<AuthService>();
-    const password = "AppFlowy123@";
-    final uid = uuid();
-    final userEmail = "[email protected]";
-    final result = await authService.signUp(
-      name: "FlowyTestUser",
-      password: password,
-      email: userEmail,
-    );
-    return result.fold(
-      (user) => user,
-      (error) {
-        throw StateError("$error");
-      },
-    );
-  }
-}
-
-class FlowyTestApp implements EntryPoint {
-  @override
-  Widget create() {
-    return Container();
-  }
-}

+ 27 - 17
frontend/scripts/makefile/desktop.toml

@@ -21,17 +21,18 @@ run_task = { name = ["setup-crate-type","sdk-build-android", "restore-crate-type
 [tasks.flowy-sdk-dev-macos]
 category = "Build"
 dependencies = ["env_check"]
-run_task = { name = ["setup-crate-type","sdk-build", "post-desktop", "restore-crate-type", "copy-to-sys-tmpdir"] }
+run_task = { name = ["setup-crate-type","sdk-build", "post-desktop", "restore-crate-type"] }
 
 [tasks.flowy-sdk-dev-windows]
 category = "Build"
 dependencies = ["env_check"]
-run_task = { name = ["setup-crate-type","sdk-build", "post-desktop", "restore-crate-type", "copy-to-sys-tmpdir"] }
+run_task = { name = ["setup-crate-type","sdk-build", "post-desktop", "restore-crate-type"] }
 
 [tasks.flowy-sdk-dev-linux]
 category = "Build"
 dependencies = ["env_check"]
-run_task = { name = ["setup-crate-type","sdk-build", "post-desktop", "restore-crate-type", "copy-to-sys-tmpdir"] }
+run_task = { name = ["setup-crate-type","sdk-build", "post-desktop", "restore-crate-type"] }
+
 
 #
 [tasks.sdk-build]
@@ -114,7 +115,7 @@ script = [
   """
     echo "🚀 🚀 🚀  Flowy-SDK(macOS) build success"
     dart_ffi_dir= set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/app_flowy/packages/flowy_sdk/${TARGET_OS}
-    lib = set lib${LIB_NAME}.${SDK_EXT}
+    lib = set lib${LIB_NAME}.${LIB_EXT}
 
     cp ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/target/${RUST_COMPILE_TARGET}/${BUILD_FLAG}/${lib} \
     ${dart_ffi_dir}/${lib}
@@ -131,7 +132,7 @@ script = [
   """
     echo "🚀 🚀 🚀  Flowy-SDK(windows) build success"
     dart_ffi_dir= set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/app_flowy/windows/flutter/dart_ffi
-    lib = set ${LIB_NAME}.${SDK_EXT}
+    lib = set ${LIB_NAME}.${LIB_EXT}
 
     # copy dll
     cp ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/target/${RUST_COMPILE_TARGET}/${BUILD_FLAG}/${lib} \
@@ -150,7 +151,7 @@ script = [
   """
     echo "🚀 🚀 🚀  Flowy-SDK(linux) build success"
     dart_ffi_dir= set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/app_flowy/linux/flutter/dart_ffi
-    lib = set lib${LIB_NAME}.${SDK_EXT}
+    lib = set lib${LIB_NAME}.${LIB_EXT}
 
     # copy dll
     cp ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/target/${RUST_COMPILE_TARGET}/${BUILD_FLAG}/${lib} \
@@ -163,25 +164,34 @@ script = [
 ]
 script_runner = "@duckscript"
 
-[tasks.copy-to-sys-tmpdir]
+[tasks.test-lib-build]
+category = "Build"
+dependencies = ["env_check"]
+run_task = { name = ["setup-test-crate-type","test-sdk-build", "copy-to-sandbox-folder", "restore-test-crate-type"] }
+
+[tasks.test-sdk-build]
 private = true
 script = [
   """
-    # Copy the flowy_sdk lib to system temp directory for flutter unit test.
-    lib = set lib${LIB_NAME}.${SDK_EXT}
-    dest = set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/app_flowy/.sandbox/${lib}
-    rm ${dest}
-    cp ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/target/${RUST_COMPILE_TARGET}/${BUILD_FLAG}/${lib} \
-    ${dest}
+    cd rust-lib/
+    rustup show
+    echo cargo build --package=dart-ffi --target ${TEST_COMPILE_TARGET} --features "${FEATURES}"
+    cargo build --package=dart-ffi --target ${TEST_COMPILE_TARGET} --features "${FEATURES}"
+    cd ../
   """,
 ]
-script_runner = "@duckscript"
+script_runner = "@shell"
 
-[tasks.copy-to-sys-tmpdir.windows]
+[tasks.copy-to-sandbox-folder]
 private = true
 script = [
   """
-    # Doesn't work on windows
+    # Copy the flowy_sdk lib to system temp directory for flutter unit test.
+    lib = set lib${LIB_NAME}.${TEST_LIB_EXT}
+    dest = set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/app_flowy/.sandbox/${lib}
+    rm ${dest}
+    cp ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/rust-lib/target/${TEST_COMPILE_TARGET}/${TEST_BUILD_FLAG}/${lib} \
+    ${dest}
   """,
 ]
-script_runner = "@duckscript"
+script_runner = "@duckscript"