From e0fdc5c68bda9d2f5e8d7cef57f846e7b2609c81 Mon Sep 17 00:00:00 2001 From: clszzyh Date: Tue, 26 Jul 2022 22:58:16 +0800 Subject: [PATCH 1/2] test(formula): refactor codeFragment cache && speed up event test --- .../config/locales/monolith.zh-TW.yml | 142 ----- .../config/locales/pwa.zh-TW.yml | 602 ------------------ .../src/__tests__/deadlockEvent.test.ts | 87 --- .../formula/src/__tests__/dependency.test.ts | 2 + packages/formula/src/__tests__/event.test.ts | 3 +- packages/formula/src/context/context.ts | 56 +- .../feature/event/spreadsheetDeadlockEvent.ts | 29 +- packages/formula/src/type/index.ts | 2 +- .../ui/Formula/Preview/FunctionPreview.tsx | 2 +- 9 files changed, 55 insertions(+), 870 deletions(-) delete mode 100644 apps/server-monolith/config/locales/monolith.zh-TW.yml delete mode 100644 apps/server-monolith/config/locales/pwa.zh-TW.yml delete mode 100644 packages/formula/src/__tests__/deadlockEvent.test.ts diff --git a/apps/server-monolith/config/locales/monolith.zh-TW.yml b/apps/server-monolith/config/locales/monolith.zh-TW.yml deleted file mode 100644 index 0cd36a3b0..000000000 --- a/apps/server-monolith/config/locales/monolith.zh-TW.yml +++ /dev/null @@ -1,142 +0,0 @@ -zh-TW: - meta: - lang: zh-TW - dir: ltr - noscript: 很抱歉,如果沒有啟用 JavaScript,MashCard 將無法正常工作。請訪問 %{url} 了解更多信息。 - noscript_url: https://support.google.com/admanager/answer/12654?hl=zh-Hant - unsupported_browser: - title: '請升級瀏覽器' - download_latest_browser_html: Unfortunately, MashCard has updated features that can't run on this version of your browser. - activerecord: - errors: - models: - accounts/user: - attributes: - password: - too_short: 太短 - mailer: - footer_message: 您收到這封電子郵件,是因為您在 %{host} 擁有帳號。 - copy_this_url: "如果上面的按鈕不起作用,請複制此網址:" - errors: - graphql: - argument_error: - invalid_pod: Token is invalid or expired. - pod_disable_invite: Pod is disabled for invites. - already_invited: You are already a member of this pod. - docs: - initialized_not_yet_completed: 初始化尚未完成 - target_descendants_invalid: 無效的目標 - messages: - already_confirmed: 已經驗證,請直接登入。 - confirmation_period_expired: 必須在 %{period} 內驗證,請重新申請。 - expired: 已經過期,請重新申請。 - not_found: 找不到。 - not_locked: 並未被鎖定。 - not_saved: - other: '發生 %{count} 個錯誤,%{resource} 無法儲存::' - is_not_valid_domain: 'Pod domain "%{domain}" is not available' - is_not_valid_email: 'Email "%{email}" is not available' - send_interval: Sending interval is too short, please try again after 1 minute - model_invalid: 'Validation failed: %{errors}' - email_invalid: is not an email - domain_invalid: is not a valid domain name - uuid_invalid: 不是 uuid - domain_presence_invalid: 不存在 - InvalidImageUrl: 無效的圖檔網址。 - app_error: - not_found_title: Whoops! Lost in MashCard? - not_found_content: 找不到您要搜索的頁面 - server_error_title: 哎呀!伺服器錯誤。 - server_error_content: Our servers are feeling a little down. - btn_back: 返回到首頁 - btn_return: 返回 - template: - body: '以下欄位發生問題:' - header: - other: '發生 %{count} 個錯誤,%{model} 無法儲存:' - devise: - confirmations: - confirmed: '你的電郵地址已成功確認。' - send_instructions: '您將在幾分鐘後收到一封電子郵件,內有驗證帳號的步驟說明。' - send_paranoid_instructions: '如果我們有您的信箱,您將會收到一封驗證您的帳號的電子郵件。' - failure: - already_authenticated: 您已經登入了。 - inactive: 您的帳號尚未被啟用。 - invalid: 無效的 %{authentication_keys} 或密碼。 - locked: 您的帳號已被鎖定。 - last_attempt: 您還有最後一次嘗試機會,再次失敗您的帳號將會被鎖定。 - not_found_in_database: '%{authentication_keys}或密碼錯誤。' - timeout: 您的會話已過期。請重新登錄以繼續。 - unauthenticated: 您需要先登入或註冊後才能繼續。 - unconfirmed: 您必須先確認電子信箱才能繼續使用。 - omniauth_callbacks: - failure: Could not authenticate you from %{kind} because "%{reason}". - success: Successfully authenticated from %{kind} account. - passwords: - no_token: You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided. - send_instructions: You will receive an email with instructions on how to reset your password in a few minutes. - send_paranoid_instructions: If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes. - updated: Your password has been changed successfully. You are now signed in. - updated_not_active: Your password has been changed successfully. - registrations: - destroyed: Bye! Your account has been successfully cancelled. We hope to see you again soon. - signed_up: You have signed up successfully. - signed_up_but_inactive: You have signed up successfully. However, we could not sign you in because your account is not yet activated. - signed_up_but_locked: You have signed up successfully. However, we could not sign you in because your account is locked. - signed_up_but_unconfirmed: A verification link has been sent to your email address. Please click on the verification link in the confirmation email to complete the sign-up process. - update_needs_confirmation: You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirmation link to confirm your new email address. - updated: Your account has been updated successfully. - unlock_instructions: - send_instructions: 'You will receive an email with instructions for how to unlock your account in a few minutes.' - send_paranoid_instructions: 'If your account exists, you will receive an email with instructions for how to unlock it in a few minutes.' - unlocked: 'Your account has been unlocked successfully. Please sign in to continue.' - mailer: - confirmation_instructions: - you_can_confirm_your_account_email_through_the_link_below: 'Please confirm this email address for your MashCard account by clicking on the button below' - subject: 'Confirmation Email' - reset_password_instructions: - subject: 'Reset password instructions' - unlock_instructions: - subject: 'Unlock instructions' - email_changed: - subject: 'Email Changed' - password_change: - subject: 'Password Changed' - sessions: - signed_in: 'Signed in successfully.' - signed_out: 'Signed out successfully.' - already_signed_out: 'Signed out successfully.' - accounts: - app_title: MashCard Accounts - provider: - email_password: Email & Password - sessions: - sign_in: Sign In - sign_up: Sign Up - reset_password: Reset Password - sign_in_to_mashcard: Sign into MashCard - more_login_options: More Login Options - login_via: 'Sign in with %{provider}' - email: Email - password: Password - remember_me: Remember me - sign_up_with_email: Sign Up - resend_confirmed_email: 重新發送確認電郵 - confirmation_email_required_heading: 快完成了! - forget_password: 忘記密碼 - confirm_password: 確認密碼 - sign_up_via: '使用 %{provider} 註冊' - name: 'Name' - domain: 'Domain Name' - domain_description: '只允许字母和数字' - agree_to_agreement: 'Sign Up indicate you agree to our <0>User Agreement.' - resend_after: 'Resendable after %{ms}' - common: - confirm_not_match: '%{field} and confirm %{field} do not match' - errors: - invalid_operation_type: '操作類型無效' - invalid_pod_domain: 'No access to the pod domain' - pod_has_already_switched: 'Pod has already switched' - pod_exist: 'Pod has already exist' - user_not_exist: "沒有這個使用者" - pod_not_exist: "Pod doesn't exist" diff --git a/apps/server-monolith/config/locales/pwa.zh-TW.yml b/apps/server-monolith/config/locales/pwa.zh-TW.yml deleted file mode 100644 index d9f8fe8c9..000000000 --- a/apps/server-monolith/config/locales/pwa.zh-TW.yml +++ /dev/null @@ -1,602 +0,0 @@ -zh-TW: - settings: - app_title: MashCard 設置 - personal_pod_desc: My Pod - group_pod_desc: Team Pod - errors: - invalid_operation_type: Invalid operation type - menu: - general: 一般設定 - account: Account - team: Team Pod - logs: 安全記錄檔 - general: - user_profile: User Profile - group_profile: Group Profile - update_profile: Update Profile - change_domain: Change Domain Name - change_domain_btn: 更新 - change_domain_desc: Unless you really need it, we recommended that you do not change your pod domain. This will cause the rela.. - change_domain_more: 進一步瞭解 - avatar_uploaded_success: Avatar uploaded successfully. - avatar_uploaded_error: Avatar uploaded failed. - avatar_updated: Avatar updated successfully. - profile_updated: Profile updated successfully. - display: Display - timezone: 時區 - locale: 語言設定 - update_appearance: 保存外觀 - account: - joined_team_pods: Joined Team Pods - leave_btn: Leave - remove_btn: 移除 - owner_cant_leave_tips: You are the owner of this pod. You can not leave it. - leave_pod_confirm: Are you sure you want to leave %{pod}? - pod_leave_success: You have left %{pod} successfully. - delete_account: 刪除帳號 - delete_account_desc: Since you delete your account, there is no going back. Please be certain. - delete_account_tip: You have left the %{pods} Pod - delete_account_unavailable: | - This account is a member/owner of the following team pods: %{pods}. To delete this account, please transfer ownership and leave or delete all your team pods. - delete_account_btn: 刪除您的帳戶 - delete_account_modal_title: Are you sure you want to delete your account? - delete_account_modal_desc: | - This is a non-reversible action that will permanently delete all your data and cannot be undone.
- You will no longer be billed, and your domain will be available for anyone to use.
- delete_account_confirm: 'To verify, type your pod domain %{domain} below:' - delete_account_confirm_btn: Confirm Delete - delete_account_confirm_cancel: cancel - team: - members: Members - leave_user_confirm: Are you sure remove %{user} from this pod? - user_leave_success: User %{user} has left pod successfully. - delete_pod: Delete This Pod - delete_pod_desc: Please be sure that once deleted. - delete_pod_btn: Delete This Team Pod - delete_pod_modal_title: Are you sure you want to delete this team pod? - delete_pod_modal_desc: | - This is a non-reversible action that will permanently delete all your data and cannot be undone. Your team pod's username will be available for anyone to use.
- Type out the name of the team pod you would like to delete below. - delete_pod_confirm: 'To verify, type your team pod domain %{domain} below:' - delete_pod_confirm_btn: Delete Pod - invite: 邀請成員 - invite_label: Enable Invite link - invite_desc: Manage the team pod's invite link. - invite_enable_updated: Invite link Settings updated successfully. - invite_secret_reset: Reset - invite_secret_reset_confirm: Are you sure you want to reset the secret? This will invalidate the current invite link. - editor: - placeholder: Type '/' for commands - copy_hint: Copied to clipboard. - explorer_menu: - title: Explore - search: - placeholder: Search - discussion: - title: Comments - tabs: - all: All - resolved: Resolved - delete_message: 確定要刪除此評論嗎? - editor: - placeholder: 評論 - send: 發送 - cancel: 撤銷 - history: - title: History - toolbar: - separator: Menu separator - blocks: - text: - label: Text - h1: - label: Heading 1 - h2: - label: Heading 2 - h3: - label: Heading 3 - h4: - label: Heading 4 - h5: - label: Heading 5 - bulletedList: - label: 符號列表 - orderedList: - label: 數字列表 - taskList: - label: 待辦事項 - link: - label: 鏈接 - embed: - label: 內嵌 - upload: - label: 本地端檔案 - gallery: - label: 相冊 - spreadsheet: - label: 試算表 - formula: - label: 公式 - divider: - label: 分隔線 - toc: - label: 目錄 - placeholder: 添加標題/錨點以創建目錄 - untitled: 無標題 - subPageMenu: - label: 子頁面菜單 - code: - label: 程式碼 - blockquote: - label: 引用 - block_actions: - basic: - cut: 剪下 - copy: 複製 - move: 移動 - delete: 刪除 - transform: 變成 - embed_block: - download: 下載 - full_screen: 全螢幕 - attachment_mode: 轉到文本視圖 - preview_mode: 轉到預覽視圖 - add_block: 在下面添加塊 - blocks: - text: 文本 - h1: 標題 1 - h2: 標題 2 - h3: 標題 3 - h4: 標題 4 - h5: 標題 5 - numbered_list: 數字列表 - bulleted_list: 符號列表 - formula: 公式 - code: 程式碼 - spreadsheet: 試算表 - upload: 上傳 - gallery: Gallery - slash_menu: - title: Slash menu - recent: Recently used - type: Type - suggestion: Suggestions - no_suggestion: No result - footer: Explore - tooltip: Explore slash menu - explorer_menu: - group: - data: - label: Data - embed: - label: Embed - text: - label: Text - others: - label: Others - items: - explore: - label: Explore - bubble_menu: - node: - section_title: Turns into - items: - paragraph: Text - heading1: Heading 1 - heading2: Heading 2 - heading3: Heading 3 - heading4: Heading 4 - heading5: Heading 5 - bulletList: Bulleted list - orderedList: Numbered list - formula: Formula - bold: - title: Bold - italic: - title: Italic - underline: - title: Underline - strike: - title: Strike - fontColor: - title: Font color - text_color: - label: Text Color - bg_color: - label: Background - reset_button: - label: Reset - comment: - title: Comment - formula: - title: Formula - anchor: - add: Mark as anchor - remove: Remove anchor mark - link: - title: Link - placeholder: Paste link - confirm: Link to web page - copy: Copy link - delete: Remove link - image_block: - hint: Add an image - deletion_confirm: - title: Are you sure you want to delete this property? - ok: 刪除 - cancel: 取消 - menu: - copy: 複製鏈接 - delete: 刪除 - import_sources: - link: - placeholder: 粘貼圖片鏈接... - button_text: 嵌入圖片 - button_hint: 適用於網絡上的任何圖像 - upload: - button_text: 選擇圖片 - formula: - menu: - delete_confirm: - title: Are you sure you want to delete this property? - ok: 刪除 - cancel: 取消 - header: 公式 - name: 名稱 - color: 顏色 - result: '=' - save: 保存公式 - delete: 刪除 - cancel: 取消 - action_panel: - more: - duplicate: 複製 - copy: 複製鏈接 - delete: 刪除 - delete_confirm: 確認 - delete_cancel: 取消 - code_block: - copy_code: 複製內容 - default_language: 純文字 - search_placeholder: 搜尋 - deletion_confirm: - title: Are you sure you want to delete this property? - ok: Delete - cancel: Cancel - languages: - 'plain text': 純文字 - markdown: Markdown - css: CSS - javascript: JavaScript - typescript: TypeScript - bash: Bash - json: JSON - yaml: YAML - sql: SQL - cpp: C/C++ - csharp: 'C#' - java: Java - python: Python - ruby: Ruby - objectivec: Objective-C - docker: Dockerfile - elixir: Elixir - rust: Rust - lisp: Lisp - haskell: Haskell - php: PHP - go: Go - kotlin: Kotlin - graphql: GraphQL - powershell: PowerShell - groovy: Groovy - solidity: Solidity - xml-doc: XML - lua: Lua - scala: Scala - matlab: Matlab - applescript: AppleScript - arduino: Arduino - basic: BASIC - diff: Diff - r: R - swift: Swift - toml: TOML - tcl: TCL - wasm: WASM - ebnf: EBNF - latex: LaTeX - tsx: TSX - jsx: JSX - protobuf: Protocol Buffer - ignore: .ignore files - regex: Regex - ini: INI - properties: Properties - embed_block: - zoom_in: - tooltip: Zoom In - zoom_out: - tooltip: Zoom Out - align: - left: - tooltip: Align Left - center: - tooltip: Align Center - right: - tooltip: Align Right - full_width: - tooltip: Align Full Width - full_screen: - tooltip: Full Screen - edit: - tooltip: Edit - view_types: - card: - name: card view - preview: - name: preview view - unavailable: - tip: Unable to preview content. - link_button: Open Link - text: - name: text view - embed_types: - link: - label: Add a link to web or file. - description: You can add a link to web or file. - panel: - link_validate: Please input valid link first. - submit_error: Please make sure link is valid and then try again. - head: 嵌入 - text: - placeholder: Text to display - link: - placeholder: 貼上連結 - upload: - label: You can upload anything locally. - description: 上傳圖片、PDF、Word、PPT、Excel等。 - types: - gallery: - search: - placeholder: Search... - label: 從 Unsplash 中選擇一張圖片。 - description: Unsplash image. - user_block: - anonymous: 匿名 - page_link_block: - untitled: 無標題 - mention: - people: - head: People - no_content: People no result - page_link: - head: 連結到頁面 - no_content: 頁面沒有結果 - spreadsheet: - delete: 刪除 - copy: 複製 - row: - actions: Actions - add_above: Add row above - add_below: Add row below - delete: Delete - column: - actions: Actions - add_left: Add column to the left - add_right: Add column to the right - delete: 刪除 - table: - untitled: 無標題 - new_row: - text: 新 - remove_row: - text: 刪除 - title: Are you sure you want to delete this row? - ok: Delete - cancel: 撤銷 - remove_column: - text: 刪除 - title: Are you sure you want to delete this property? - ok: Delete - cancel: Cancel - column_default_name: Column - column_type: Property Type - column_types: - basic: Basic - text: Text - select: Select - date: Date - date-range: Date Range - filter: - text: Filter - title: Filter for My All Data - remove: Remove - duplicate: Duplicate - where: Where - add_a_filter: 新增篩選器 - add_a_filter_group: Add a filter group - add_a_filter_group_desc: A group to nest more filters - hint: | - Use a filter to: - Show tasks assigned to me. - Show only notes with a certain tag. - Hide completed tasks. - collection_types: - intersection: And - union: Or - matches: - is: Is - is_not: Is not - is_on: Is - is_not_on: Is not - is_before: Is before - is_after: Is After - is_on_or_before: Is on or before - is_on_or_after: Is on or after - contains: Contains - does_not_contain: Does not contain - starts_with: Starts with - ends_with: Ends with - is_empty: Is empty - is_not_empty: Is not empty - sort: - text: Sort - title: Sort for My All Data - hint: | - Use a sort to: - Order tasks by priority. - Show notes by creation date. - Show recently contacted customers. - docs: - app_title: MashCard - saving: 正在儲存 - user_setting: - text: User Setting - general: General - member: Member - account: Account - pod_setting: - text: Pod Setting - anonymous: - edit_button: 編輯 - search: - text: 快速搜尋 - placeholder: 搜尋頁面 - blocks: - create_pages: 新增頁面 - no_pages: No pages inside - create_sub_pages: Add Subpage - delete: Delete - rename: Rename - undo: Undo - more: Delete, Duplicate, and more... - copy_link: - button: Copy link - copied: Copied - success_message: Link copied - duplicate: - new_title: Copy of %{title} - button: Duplicate - pin: - name: Pin - add: Pin page - add_tooltip: Pin this page - remove: Unpin page - remove_tooltip: Unpin this page - trash: - name: Trash - pages: Pages - owner: Owner - deleted_at: Deleted At - all_pages: All pages - current_page: 在當前頁面 - search: Filter by page title... - not_found: No match found. - learn: Learn about deleting and restoring pages - delete_confirmation_body: Are you sure you want to delete this page permanently? - batch_delete_confirmation_body: Are you sure you want to delete these %{number} pages permanently? - delete_confirmation_ok: 刪除頁面 - delete_confirmation_cancel: Cancel - in_trash_prompt: This page is in trash. - restore_action: Restore page - hard_delete_action: Delete Page - selected: selected - discussion: - menu: Comment - tooltip: show comments on current page - history: - menu: History - tooltip: View all updates - more: - tooltip: more options - share: - menu: Share - invite: Invite - share_title: Share the page - share_to_web: Share to web - share_to_web_description: Publish and share link with anyone - allow_edit: Allow edit - learn: Learn about sharing - copy_link_button: Copy link - copy_link_button_done: 已複製 - invite_placeholder: 按用戶名添加人員 - invite_button: Invite - copy_hint: 分享網址已複製 - tooltip: Share or publish to the web - invite: - learn: Learn more about sharing - type_hint: Type or paste in pod domain above, separated by commas. - search: Add people by username - no_result: no result - button: 邀請 - confirm_button: Confirm - edit_message: Can edit - edit_message_description: Can edit, but not share with others. - view_message: Can view - view_message_description: Cannot edit or share with others. - no_view_message: 無法查看 - no_view_message_description: Cannot view or share with others. - remove_message: Remove - anyone_with_link: Anyone with the link - snapshots: - name: 快照 - restore: 還原版本 - restoring: Restoring... - cancel: 撤銷 - empty: Version history is empty - pods: - domain: Domain Name - name: Name - pod_input_placeholder: Input Pod Name - bio: - label: Bio - placeholder: Tell others a little about yourself. - upload_avatar: Upload Photo - required: - domain: Domain is required - name: Name is required - create: - success: Create successfully. - update: - success: Update successfully. - menu: - create_new_pod: Create New Pod - logout: 登出 - title: - add_icon: 新增圖示 - add_cover: 添加封面 - remove_cover: 移除 - change_cover: 變更封面 - reposition: Reposition - untitled: Untitled - document_icon: - import_sources: - link: - placeholder: Paste the image link... - button_text: Submit - button_hint: Works with any image from the web - type_label: Link - invalidImageUrlMessage: 無效的圖檔網址。 - upload: - button_hint: 推薦尺寸為 280x280 像素 - button_text: 選擇圖片 - type_label: 上傳圖片 - document_cover: - import_sources: - link: - placeholder: Paste the image link... - button_text: Submit - button_hint: Works with any image from the web - invalidImageUrlMessage: Invalid image url - type_label: Link - upload: - button_hint: 'Recommended image size: wider than 1500 pixels' - button_text: Choose an image - type_label: Upload an Image - formats: - days: - today: Today - yesterday: Yesterday - date: 'YYYY-MM-DD' - time: 'HH:mm:ss' diff --git a/packages/formula/src/__tests__/deadlockEvent.test.ts b/packages/formula/src/__tests__/deadlockEvent.test.ts deleted file mode 100644 index 7e12e5b3c..000000000 --- a/packages/formula/src/__tests__/deadlockEvent.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { interpret, parse, generateVariable } from '../grammar' -import { buildEvent, makeContext } from '../tests/testHelper' -import { buildTestCases, matchObject, trackTodo } from '../tests' -import { uuid } from '@mashcard/active-support' -import { MashcardEventBus } from '@mashcard/schema' -import { fetchResult } from '../context' - -const [input] = buildTestCases(['spreadsheetDeadlockEvent']) - -describe('deadlockEvent', () => { - let ctx: Awaited> - beforeEach(async () => { - ctx = await makeContext({ - ...input.options, - uuidFunction: index => uuid(), - initializeOptions: { username: uuid() } - }) - }) - - trackTodo(it, input.eventTestCases) - - it.each([...input.eventTestCases.slice(0, 30)])('$jestTitle', async args => { - const newCtx = { ...ctx, meta: ctx.buildMeta(args) } - const parseResult = parse(newCtx) - const triggerTest = [] - - const eventListeners1 = [] - - if (args.saveEvents) { - for (const event of args.saveEvents(newCtx)) { - const f = jest.fn() - const subscription = MashcardEventBus.subscribe(event.event, e => f(e.payload), { - subscribeId: args.jestTitle, - eventId: event.eventId - }) - triggerTest.push({ f, event, label: 'save' }) - eventListeners1.push(subscription) - } - } - - const tempT = await interpret({ ctx: newCtx, parseResult }) - const variable = generateVariable({ formulaContext: ctx.formulaContext, t: tempT }) - await variable.save() - const resultBefore = await variable.t.task.variableValue - - eventListeners1.forEach(listener => listener.unsubscribe()) - - expect(matchObject(resultBefore.result)).toStrictEqual(args.resultBefore) - - const eventListeners2 = [] - - if (args.triggerEvents) { - for (const event of args.triggerEvents(newCtx)) { - const f = jest.fn() - const subscription = MashcardEventBus.subscribe(event.event, e => f(e.payload), { - subscribeId: args.jestTitle, - eventId: event.eventId - }) - triggerTest.push({ f, event, label: 'event' }) - eventListeners2.push(subscription) - } - } - - await buildEvent(args.events)(newCtx) - - eventListeners2.forEach(listener => listener.unsubscribe()) - - for (const { f, event, label } of triggerTest) { - const callLength = event.callLength ?? 1 - expect([label, event.event.eventType, f.mock.calls.length]).toEqual([label, event.event.eventType, callLength]) - if (callLength > 0) { - // eslint-disable-next-line jest/no-conditional-expect - expect([label, event.event.eventType, f.mock.calls[0][0]]).toMatchObject([ - label, - event.event.eventType, - event.payload ?? {} - ]) - } - } - - expect(variable.t.task.async).toBe(args.resultAfterAsync ?? false) - const resultAfter = fetchResult(variable.t) - - expect(matchObject(resultAfter)).toStrictEqual(args.resultAfter ?? args.resultBefore) - expect(variable.t.variableParseResult).toMatchObject(args.variableParseResultAfter ?? {}) - }) -}) diff --git a/packages/formula/src/__tests__/dependency.test.ts b/packages/formula/src/__tests__/dependency.test.ts index 1d214ac0e..f30f98c85 100644 --- a/packages/formula/src/__tests__/dependency.test.ts +++ b/packages/formula/src/__tests__/dependency.test.ts @@ -6,12 +6,14 @@ import { uuid } from '@mashcard/active-support' import { BlockType } from '../controls' import { DependencyNames } from '../tests/feature/dependency' import { matchObject } from '../tests/testMock' +import { MashcardEventBus } from '@mashcard/schema' const [input, testCases] = buildTestCases(DependencyNames) describe('dependency', () => { let ctx: Awaited> beforeEach(async () => { + MashcardEventBus.reset() ctx = await makeContext({ ...input.options, uuidFunction: index => uuid() }) }) diff --git a/packages/formula/src/__tests__/event.test.ts b/packages/formula/src/__tests__/event.test.ts index f96b820c0..3e0b0c69a 100644 --- a/packages/formula/src/__tests__/event.test.ts +++ b/packages/formula/src/__tests__/event.test.ts @@ -5,11 +5,12 @@ import { uuid } from '@mashcard/active-support' import { MashcardEventBus } from '@mashcard/schema' import { fetchResult } from '../context' -const [input] = buildTestCases(EventNames.filter(e => e !== 'spreadsheetDeadlockEvent')) +const [input] = buildTestCases(EventNames) describe('event', () => { let ctx: Awaited> beforeEach(async () => { + MashcardEventBus.reset() ctx = await makeContext({ ...input.options, uuidFunction: index => uuid(), diff --git a/packages/formula/src/context/context.ts b/packages/formula/src/context/context.ts index 8eb96dad0..2a3e22697 100644 --- a/packages/formula/src/context/context.ts +++ b/packages/formula/src/context/context.ts @@ -473,28 +473,46 @@ export class FormulaContext implements ContextInterface { } } - private parseCodeFragments(input: string): CodeFragmentWithIndex[] { - const lexResult: ILexingResult = FormulaLexer.tokenize(input) - if (lexResult.errors.length > 0) { - return [] - } - const parser = new FormulaParser() - const codeFragmentVisitor = new CodeFragmentVisitor({ - ctx: { - formulaContext: this, - meta: { name: 'unknown', input, namespaceId: '', variableId: '', position: 0, richType: { type: 'normal' } }, - interpretContext: { ctx: {}, arguments: [] } + private parseCodeFragments(input: string): () => CodeFragmentWithIndex[] { + let result: CodeFragmentWithIndex[] | undefined + + return () => { + if (!result) { + const lexResult: ILexingResult = FormulaLexer.tokenize(input) + if (lexResult.errors.length > 0) { + result = [] + } else { + const parser = new FormulaParser() + const codeFragmentVisitor = new CodeFragmentVisitor({ + ctx: { + formulaContext: this, + meta: { + name: 'unknown', + input, + namespaceId: '', + variableId: '', + position: 0, + richType: { type: 'normal' } + }, + interpretContext: { ctx: {}, arguments: [] } + } + }) + const tokens = lexResult.tokens + parser.input = tokens + + const cst: CstNode = parser.startExpression() + const { codeFragments }: { codeFragments: CodeFragment[] } = codeFragmentVisitor.visit(cst, { + type: 'any' + }) ?? { + codeFragments: [] + } + + result = codeFragments.map((c, index) => ({ ...c, index })) + } } - }) - const tokens = lexResult.tokens - parser.input = tokens - const cst: CstNode = parser.startExpression() - const { codeFragments }: { codeFragments: CodeFragment[] } = codeFragmentVisitor.visit(cst, { type: 'any' }) ?? { - codeFragments: [] + return result } - - return codeFragments.map((c, index) => ({ ...c, index })) } public static getFormulaInstance(args: FormulaContextArgs): FormulaContext { diff --git a/packages/formula/src/tests/feature/event/spreadsheetDeadlockEvent.ts b/packages/formula/src/tests/feature/event/spreadsheetDeadlockEvent.ts index 574fbddeb..553370c99 100644 --- a/packages/formula/src/tests/feature/event/spreadsheetDeadlockEvent.ts +++ b/packages/formula/src/tests/feature/event/spreadsheetDeadlockEvent.ts @@ -1,4 +1,3 @@ -import { sampleSize } from '@mashcard/active-support' import { Cell, Column, Row } from '../../../controls' import { generateUUIDs } from '../../testHelper' import { mockCell } from '../../testMock' @@ -168,23 +167,19 @@ const deleteFirstRowEvent: DistributeEvents = [ const definitionCases: (column: string, row: string) => Array<{ definition: string; logicRow?: true; error: any }> = ( column, row -) => - sampleSize( - [ - { definition: `=${column}.${row}`, error: PARSE_ERROR }, - { definition: `=spreadsheet1.${column}.${row}`, error: PARSE_ERROR }, - { definition: `=ThisRecord.${column}.${row}`, error: PARSE_ERROR }, - { definition: `=ThisRow.${column}`, logicRow: true, error: PARSE_ERROR }, +) => [ + { definition: `=${column}.${row}`, error: PARSE_ERROR }, + { definition: `=spreadsheet1.${column}.${row}`, error: PARSE_ERROR }, + { definition: `=ThisRecord.${column}.${row}`, error: PARSE_ERROR }, + { definition: `=ThisRow.${column}`, logicRow: true, error: PARSE_ERROR }, - { definition: `=${column}[${row}]`, error: INTERPRET_ERROR }, - { definition: `=spreadsheet1.${column}[${row}]`, error: INTERPRET_ERROR }, - { definition: `=ThisRecord.${column}[${row}]`, error: INTERPRET_ERROR }, - { definition: `=spreadsheet1["${column}"][${row}]`, error: INTERPRET_ERROR }, - { definition: `=ThisRecord["${column}"][${row}]`, error: INTERPRET_ERROR }, - { definition: `=ThisRow["${column}"]`, logicRow: true, error: INTERPRET_ERROR } - ], - 5 - ) + { definition: `=${column}[${row}]`, error: INTERPRET_ERROR }, + { definition: `=spreadsheet1.${column}[${row}]`, error: INTERPRET_ERROR }, + { definition: `=ThisRecord.${column}[${row}]`, error: INTERPRET_ERROR }, + { definition: `=spreadsheet1["${column}"][${row}]`, error: INTERPRET_ERROR }, + { definition: `=ThisRecord["${column}"][${row}]`, error: INTERPRET_ERROR }, + { definition: `=ThisRow["${column}"]`, logicRow: true, error: INTERPRET_ERROR } +] export const SpreadsheetDeadlockEventTestCase: TestCaseInterface = { name: 'spreadsheetDeadlockEvent', diff --git a/packages/formula/src/type/index.ts b/packages/formula/src/type/index.ts index d99476833..cd128671a 100644 --- a/packages/formula/src/type/index.ts +++ b/packages/formula/src/type/index.ts @@ -408,7 +408,7 @@ export interface ContextInterface { interface Example { readonly input: Definition readonly output: AnyFunctionResult | null - readonly codeFragments?: CodeFragmentWithIndex[] + readonly codeFragments?: () => CodeFragmentWithIndex[] } export interface BaseFunctionContext { diff --git a/packages/legacy-editor/src/components/ui/Formula/Preview/FunctionPreview.tsx b/packages/legacy-editor/src/components/ui/Formula/Preview/FunctionPreview.tsx index 5baa2543c..e383eaf76 100644 --- a/packages/legacy-editor/src/components/ui/Formula/Preview/FunctionPreview.tsx +++ b/packages/legacy-editor/src/components/ui/Formula/Preview/FunctionPreview.tsx @@ -46,7 +46,7 @@ export const FunctionPreview: React.FC = ({ functionClause
Example
{functionClause.examples.map((example, index) => (
- +
={JSON.stringify(example?.output?.result)}
From bb3438d5ba7e8f7bb6e9360c7e37cffca3d4ee29 Mon Sep 17 00:00:00 2001 From: clszzyh Date: Tue, 26 Jul 2022 23:03:11 +0800 Subject: [PATCH 2/2] fix: lint Signed-off-by: clszzyh --- .../AutocompleteList/__tests__/AutocompleteList.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/legacy-editor/src/components/ui/Formula/AutocompleteList/__tests__/AutocompleteList.test.tsx b/packages/legacy-editor/src/components/ui/Formula/AutocompleteList/__tests__/AutocompleteList.test.tsx index 7aa91825d..5dc9c0d2d 100644 --- a/packages/legacy-editor/src/components/ui/Formula/AutocompleteList/__tests__/AutocompleteList.test.tsx +++ b/packages/legacy-editor/src/components/ui/Formula/AutocompleteList/__tests__/AutocompleteList.test.tsx @@ -183,7 +183,7 @@ describe('AutocompleteList', () => { ], examples: [ { - codeFragments: [], + codeFragments: () => [], input: 'input', output: null }