From e7420969c23b7c0a4147f0f81735b735e484cc2c Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 5 Oct 2022 15:03:05 +0200 Subject: [PATCH 1/6] feat: api keys detail --- package-lock.json | 28 +-- package.json | 4 +- src/lib/components/collapsible.svelte | 20 +- src/lib/components/collapsibleItem.svelte | 14 ++ src/lib/components/index.ts | 1 + src/lib/constants.ts | 206 +++++++++++------- src/lib/elements/forms/index.ts | 1 + src/lib/elements/forms/inputDateTime.svelte | 58 +++++ .../project-[project]/keys/+layout.svelte | 22 -- .../project-[project]/keys/+page.svelte | 62 ------ .../project-[project]/keys/_create.svelte | 69 ------ .../keys/key/[key]/+page.svelte | 35 --- .../keys/[key]/+page@project-[project].svelte | 68 ++++-- 13 files changed, 267 insertions(+), 321 deletions(-) create mode 100644 src/lib/components/collapsibleItem.svelte create mode 100644 src/lib/elements/forms/inputDateTime.svelte delete mode 100644 src/routes/console/project-[project]/keys/+layout.svelte delete mode 100644 src/routes/console/project-[project]/keys/+page.svelte delete mode 100644 src/routes/console/project-[project]/keys/_create.svelte delete mode 100644 src/routes/console/project-[project]/keys/key/[key]/+page.svelte diff --git a/package-lock.json b/package-lock.json index 0585154663..8154711ade 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,8 @@ "version": "0.0.1", "dependencies": { "@aw-labs/appwrite-console": "^6.0.0", - "@aw-labs/icons": "0.0.0-57", - "@aw-labs/ui": "0.0.0-57", + "@aw-labs/icons": "0.0.0-58", + "@aw-labs/ui": "0.0.0-58", "echarts": "^5.4.0", "tippy.js": "^6.3.7", "web-vitals": "^2.1.4" @@ -77,14 +77,14 @@ } }, "node_modules/@aw-labs/icons": { - "version": "0.0.0-57", - "resolved": "https://registry.npmjs.org/@aw-labs/icons/-/icons-0.0.0-57.tgz", - "integrity": "sha512-HmXSTSP3GEBi5awFk0APTTNdM10DDIBCTnxi3BJGlsXo+SXnpVikoMk6RZltNLH7MRfPQNx+VfJ2bOC+hlW8ZQ==" + "version": "0.0.0-58", + "resolved": "https://registry.npmjs.org/@aw-labs/icons/-/icons-0.0.0-58.tgz", + "integrity": "sha512-xUD5DQcYVNiKhDSpxMO24G/4l7txgAdwochK01tJA6wXhuPAcp5Yjuofjm2bGkMzCuze4Vs+SVvhsBxzVXRPrA==" }, "node_modules/@aw-labs/ui": { - "version": "0.0.0-57", - "resolved": "https://registry.npmjs.org/@aw-labs/ui/-/ui-0.0.0-57.tgz", - "integrity": "sha512-a/nKqu9nHysTF7bIOLo+ZN1zKpCHfv+jHGixU0SGXchTNAmj2OXClZNk3XfMmwnPD6CiF4cG6YRdbmpx+TTXgA==", + "version": "0.0.0-58", + "resolved": "https://registry.npmjs.org/@aw-labs/ui/-/ui-0.0.0-58.tgz", + "integrity": "sha512-W3bTvAPX4ig5qLBvGn/VpNaDk62RqO4oDa0poube2WuElkVvaGwFAR0wCwmisdi2NeXyGJqt20g3Y/Mz4K2yMA==", "dependencies": { "@aw-labs/icons": "*" } @@ -8134,14 +8134,14 @@ } }, "@aw-labs/icons": { - "version": "0.0.0-57", - "resolved": "https://registry.npmjs.org/@aw-labs/icons/-/icons-0.0.0-57.tgz", - "integrity": "sha512-HmXSTSP3GEBi5awFk0APTTNdM10DDIBCTnxi3BJGlsXo+SXnpVikoMk6RZltNLH7MRfPQNx+VfJ2bOC+hlW8ZQ==" + "version": "0.0.0-58", + "resolved": "https://registry.npmjs.org/@aw-labs/icons/-/icons-0.0.0-58.tgz", + "integrity": "sha512-xUD5DQcYVNiKhDSpxMO24G/4l7txgAdwochK01tJA6wXhuPAcp5Yjuofjm2bGkMzCuze4Vs+SVvhsBxzVXRPrA==" }, "@aw-labs/ui": { - "version": "0.0.0-57", - "resolved": "https://registry.npmjs.org/@aw-labs/ui/-/ui-0.0.0-57.tgz", - "integrity": "sha512-a/nKqu9nHysTF7bIOLo+ZN1zKpCHfv+jHGixU0SGXchTNAmj2OXClZNk3XfMmwnPD6CiF4cG6YRdbmpx+TTXgA==", + "version": "0.0.0-58", + "resolved": "https://registry.npmjs.org/@aw-labs/ui/-/ui-0.0.0-58.tgz", + "integrity": "sha512-W3bTvAPX4ig5qLBvGn/VpNaDk62RqO4oDa0poube2WuElkVvaGwFAR0wCwmisdi2NeXyGJqt20g3Y/Mz4K2yMA==", "requires": { "@aw-labs/icons": "*" } diff --git a/package.json b/package.json index 9ae2f78f9f..d7c3234f5f 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,8 @@ }, "dependencies": { "@aw-labs/appwrite-console": "^6.0.0", - "@aw-labs/icons": "0.0.0-57", - "@aw-labs/ui": "0.0.0-57", + "@aw-labs/icons": "0.0.0-58", + "@aw-labs/ui": "0.0.0-58", "echarts": "^5.4.0", "tippy.js": "^6.3.7", "web-vitals": "^2.1.4" diff --git a/src/lib/components/collapsible.svelte b/src/lib/components/collapsible.svelte index 3647c2ec8b..245eec7810 100644 --- a/src/lib/components/collapsible.svelte +++ b/src/lib/components/collapsible.svelte @@ -1,21 +1,3 @@ diff --git a/src/lib/components/collapsibleItem.svelte b/src/lib/components/collapsibleItem.svelte new file mode 100644 index 0000000000..5caa6caf34 --- /dev/null +++ b/src/lib/components/collapsibleItem.svelte @@ -0,0 +1,14 @@ +
  • +
    + + + +
    +
    +
    +
    + +
    +
    +
  • diff --git a/src/lib/components/index.ts b/src/lib/components/index.ts index b6f4ffb8bb..bd3ebd58eb 100644 --- a/src/lib/components/index.ts +++ b/src/lib/components/index.ts @@ -16,6 +16,7 @@ export { default as DropList } from './dropList.svelte'; export { default as DropListItem } from './dropListItem.svelte'; export { default as DropListLink } from './dropListLink.svelte'; export { default as Collapsible } from './collapsible.svelte'; +export { default as CollapsibleItem } from './collapsibleItem.svelte'; export { default as DropTabs } from './dropTabs.svelte'; export { default as DropTabsItem } from './dropTabsItem.svelte'; export { default as Avatar } from './avatar.svelte'; diff --git a/src/lib/constants.ts b/src/lib/constants.ts index aeaa77c210..08fad97b46 100644 --- a/src/lib/constants.ts +++ b/src/lib/constants.ts @@ -1,80 +1,130 @@ export const scopes = [ - 'users.read', - 'users.write', - 'teams.read', - 'teams.write', - 'collections.read', - 'collections.write', - 'attributes.read', - 'attributes.write', - 'indexes.read', - 'indexes.write', - 'documents.read', - 'documents.write', - 'files.read', - 'files.write', - 'buckets.read', - 'buckets.write', - 'functions.read', - 'functions.write', - 'execution.read', - 'execution.write', - 'locale.read', - 'avatars.read', - 'health.read' -]; - -export const events = [ - 'account.create', - 'account.update.email', - 'account.update.name', - 'account.update.password', - 'users.update.email', - 'users.update.name', - 'users.update.password', - 'account.update.prefs', - 'account.recovery.create', - 'account.recovery.update', - 'account.verification.create', - 'account.verification.update', - 'account.delete', - 'account.sessions.create', - 'account.sessions.delete', - 'account.sessions.update', - 'database.collections.create', - 'database.collections.update', - 'database.collections.delete', - 'database.attributes.create', - 'database.attributes.delete', - 'database.indexes.create', - 'database.indexes.delete', - 'database.documents.create', - 'database.documents.update', - 'database.documents.delete', - 'functions.create', - 'functions.update', - 'functions.delete', - 'functions.deployments.create', - 'functions.deployments.update', - 'functions.deployments.delete', - 'functions.executions.create', - 'functions.executions.update', - 'storage.files.create', - 'storage.files.update', - 'storage.files.delete', - 'storage.buckets.create', - 'storage.buckets.update', - 'storage.buckets.delete', - 'users.create', - 'users.update.prefs', - 'users.update.status', - 'users.delete', - 'users.sessions.delete', - 'teams.create', - 'teams.update', - 'teams.delete', - 'teams.memberships.create', - 'teams.memberships.update', - 'teams.memberships.update.status', - 'teams.memberships.delete' + { + scope: 'users.read', + description: "Access to read your project's users", + category: 'Authentication' + }, + { + scope: 'users.write', + description: "Access to create, update, and delete your project's users", + category: 'Authentication' + }, + { + scope: 'teams.read', + description: "Access to read your project's teams", + category: 'Authentication' + }, + { + scope: 'teams.write', + description: "Access to create, update, and delete your project's teams", + category: 'Authentication' + }, + { + scope: 'databases.read', + description: "Access to read your project's databases", + category: 'Database' + }, + { + scope: 'databases.write', + description: "Access to create, update, and delete your project's databases", + category: 'Database' + }, + { + scope: 'collections.read', + description: "Access to read your project's database collections", + category: 'Database' + }, + { + scope: 'collections.write', + description: "Access to create, update, and delete your project's database collections", + category: 'Database' + }, + { + scope: 'attributes.read', + description: "Access to read your project's database collection's attributes", + category: 'Database' + }, + { + scope: 'attributes.write', + description: + "Access to create, update, and delete your project's database collection's attributes", + category: 'Database' + }, + { + scope: 'indexes.read', + description: "Access to read your project's database collection's indexes", + category: 'Database' + }, + { + scope: 'indexes.write', + description: + "Access to create, update, and delete your project's database collection's indexes", + category: 'Database' + }, + { + scope: 'documents.read', + description: "Access to read your project's database documents", + category: 'Database' + }, + { + scope: 'documents.write', + description: "Access to create, update, and delete your project's database documents", + category: 'Database' + }, + { + scope: 'files.read', + description: "Access to read your project's storage files and preview images", + category: 'Storage' + }, + { + scope: 'files.write', + description: "Access to create, update, and delete your project's storage files", + category: 'Storage' + }, + { + scope: 'buckets.read', + description: "Access to read your project's storage buckets", + category: 'Storage' + }, + { + scope: 'buckets.write', + description: "Access to create, update, and delete your project's storage buckets", + category: 'Storage' + }, + { + scope: 'functions.read', + description: "Access to read your project's functions and code deployments", + category: 'Functions' + }, + { + scope: 'functions.write', + description: + "Access to create, update, and delete your project's functions and code deployments", + category: 'Functions' + }, + { + scope: 'execution.read', + description: "Access to read your project's execution logs", + category: 'Functions' + }, + { + scope: 'execution.write', + description: "Access to execute your project's functions", + category: 'Functions' + }, + { + scope: 'locale.read', + description: "Access to access your project's Locale service", + category: 'Other' + }, + { + scope: 'avatars.read', + description: "Access to access your project's Avatars service", + category: 'Other' + }, + { + scope: 'health.read', + description: "Access to read your project's health status", + category: 'Other' + } ]; diff --git a/src/lib/elements/forms/index.ts b/src/lib/elements/forms/index.ts index 7ed7d656fe..b0b7b47b7b 100644 --- a/src/lib/elements/forms/index.ts +++ b/src/lib/elements/forms/index.ts @@ -11,6 +11,7 @@ export { default as InputSwitch } from './inputSwitch.svelte'; export { default as InputTags } from './inputTags.svelte'; export { default as InputFile } from './inputFile.svelte'; export { default as InputCustomId } from './inputCustomId.svelte'; +export { default as InputDateTime } from './inputDateTime.svelte'; export { default as InputSearch } from './inputSearch.svelte'; export { default as InputRadio } from './inputRadio.svelte'; export { default as InputSelect } from './inputSelect.svelte'; diff --git a/src/lib/elements/forms/inputDateTime.svelte b/src/lib/elements/forms/inputDateTime.svelte new file mode 100644 index 0000000000..3869f498bf --- /dev/null +++ b/src/lib/elements/forms/inputDateTime.svelte @@ -0,0 +1,58 @@ + + + + +
    + +
    + {#if error} + {error} + {/if} +
    diff --git a/src/routes/console/project-[project]/keys/+layout.svelte b/src/routes/console/project-[project]/keys/+layout.svelte deleted file mode 100644 index 29247c421c..0000000000 --- a/src/routes/console/project-[project]/keys/+layout.svelte +++ /dev/null @@ -1,22 +0,0 @@ - - - diff --git a/src/routes/console/project-[project]/keys/+page.svelte b/src/routes/console/project-[project]/keys/+page.svelte deleted file mode 100644 index 05f59eee2d..0000000000 --- a/src/routes/console/project-[project]/keys/+page.svelte +++ /dev/null @@ -1,62 +0,0 @@ - - - - Appwrite - API Keys - - - {#if $project} - {#if $project.keys} - - - Name - Scopes - - - {#each $project.keys as key} - - - {key.name} - - {key.scopes.length} - - {/each} - -
    - {:else} - -
    -
    No API Keys Found
    -
    - You haven't created any API keys for your project yet. -
    -
    -
    - {/if} - - {/if} -
    - diff --git a/src/routes/console/project-[project]/keys/_create.svelte b/src/routes/console/project-[project]/keys/_create.svelte deleted file mode 100644 index 055b5349c6..0000000000 --- a/src/routes/console/project-[project]/keys/_create.svelte +++ /dev/null @@ -1,69 +0,0 @@ - - -
    - - Add API Key -

    - Select AllUnselect All -

    - - {#each scopes as scope} - - {/each} - - - - -
    -
    diff --git a/src/routes/console/project-[project]/keys/key/[key]/+page.svelte b/src/routes/console/project-[project]/keys/key/[key]/+page.svelte deleted file mode 100644 index 691763677d..0000000000 --- a/src/routes/console/project-[project]/keys/key/[key]/+page.svelte +++ /dev/null @@ -1,35 +0,0 @@ - - - - - {#await request} - loading - {:then response} -

    {response.name}

    - - {/await} -
    -
    diff --git a/src/routes/console/project-[project]/overview/keys/[key]/+page@project-[project].svelte b/src/routes/console/project-[project]/overview/keys/[key]/+page@project-[project].svelte index a36510ad32..a168fd26fe 100644 --- a/src/routes/console/project-[project]/overview/keys/[key]/+page@project-[project].svelte +++ b/src/routes/console/project-[project]/overview/keys/[key]/+page@project-[project].svelte @@ -2,16 +2,18 @@ import { afterNavigate } from '$app/navigation'; import { base } from '$app/paths'; import { page } from '$app/stores'; - import { CardGrid } from '$lib/components'; + import { CardGrid, Collapsible, CollapsibleItem } from '$lib/components'; import { scopes } from '$lib/constants'; import { Button, Form, FormList, - InputCheckbox, + InputChoice, InputPassword, InputText } from '$lib/elements/forms'; + import InputDateTime from '$lib/elements/forms/inputDateTime.svelte'; + import { difference } from '$lib/helpers/array'; import { toLocaleDateTime } from '$lib/helpers/date'; import { Container } from '$lib/layout'; import { updateLayout } from '$lib/stores/layout'; @@ -25,7 +27,7 @@ const projectId = $page.params.project; const keyId = $page.params.key; const activeScopes = scopes.reduce((prev, next) => { - prev[next] = false; + prev[next.scope] = false; return prev; }, {}); @@ -40,8 +42,9 @@ afterNavigate(handle); async function handle(event = null) { + const promise = key.load(projectId, keyId); if ($key?.$id !== keyId) { - await key.load(projectId, keyId); + await promise; } name ??= $key.name; @@ -121,8 +124,9 @@ $project.$id, $key.$id, $key.name, - scopes.filter((scope) => activeScopes[scope]) + selectedScoped ); + $key.scopes = selectedScoped; addNotification({ type: 'success', message: 'API Key scopes has been updated' @@ -135,11 +139,21 @@ } } + function selectAll() { + for (const scope in activeScopes) { + activeScopes[scope] = true; + } + } + function unselectAll() { for (const scope in activeScopes) { activeScopes[scope] = false; } } + + $: selectedScoped = scopes + .filter((scope) => activeScopes[scope.scope]) + .map(({ scope }) => scope); @@ -154,7 +168,7 @@

    - Last accessed: {toLocaleDateTime($key.$updatedAt)}
    + Last accessed: {toLocaleDateTime($key.accessedAt)}
    Scopes granted: {$key.scopes.length}

    @@ -206,18 +220,36 @@ practice to allow only the permissions you need to meet your project goals.

    - - {#each scopes as scope} - +
    + + +
    + + {#each ['Authentication', 'Database', 'Functions', 'Storage', 'Other'] as category} + + {category} + + {#each scopes.filter((s) => s.category === category) as scope} + + {scope.description} + + {/each} + + {/each} -
    +
    - + @@ -227,11 +259,7 @@

    Choose any name that will help you distinguish between API keys.

    - + @@ -250,7 +278,7 @@
    {$key.name}
    -

    Last accessed: {toLocaleDateTime($key.$updatedAt)}

    +

    Last accessed: {toLocaleDateTime($key.accessedAt)}

    From f802afb98e0d87800de6ebd3ffdf055e17776ee6 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 5 Oct 2022 17:40:55 +0200 Subject: [PATCH 2/6] fix: re-usable scopes and secret --- src/lib/components/index.ts | 1 + src/lib/components/secret.svelte | 28 ++++++ .../overview/keys/+page.svelte | 2 +- .../keys/[key]/+page@project-[project].svelte | 96 +++---------------- .../overview/keys/create.svelte | 27 ++---- .../overview/keys/scopes.svelte | 72 ++++++++++++++ 6 files changed, 124 insertions(+), 102 deletions(-) create mode 100644 src/lib/components/secret.svelte create mode 100644 src/routes/console/project-[project]/overview/keys/scopes.svelte diff --git a/src/lib/components/index.ts b/src/lib/components/index.ts index bd3ebd58eb..96e13637bd 100644 --- a/src/lib/components/index.ts +++ b/src/lib/components/index.ts @@ -27,3 +27,4 @@ export { default as Search } from './search.svelte'; export { default as GridItem1 } from './gridItem1.svelte'; export { default as Steps } from './steps.svelte'; export { default as Step } from './step.svelte'; +export { default as Secret } from './secret.svelte'; diff --git a/src/lib/components/secret.svelte b/src/lib/components/secret.svelte new file mode 100644 index 0000000000..458005a93e --- /dev/null +++ b/src/lib/components/secret.svelte @@ -0,0 +1,28 @@ + + +
    + {#if show} + {value} + {:else} + •••••• + {/if} +
    + + + + +
    +
    diff --git a/src/routes/console/project-[project]/overview/keys/+page.svelte b/src/routes/console/project-[project]/overview/keys/+page.svelte index ebe4a4379b..5f611048c5 100644 --- a/src/routes/console/project-[project]/overview/keys/+page.svelte +++ b/src/routes/console/project-[project]/overview/keys/+page.svelte @@ -39,7 +39,7 @@ {key.name} - {toLocaleDateTime(key.$createdAt)} + {key.accessedAt ? toLocaleDateTime(key.accessedAt) : 'never'} {toLocaleDateTime(key.$updatedAt)} diff --git a/src/routes/console/project-[project]/overview/keys/[key]/+page@project-[project].svelte b/src/routes/console/project-[project]/overview/keys/[key]/+page@project-[project].svelte index a168fd26fe..e843328238 100644 --- a/src/routes/console/project-[project]/overview/keys/[key]/+page@project-[project].svelte +++ b/src/routes/console/project-[project]/overview/keys/[key]/+page@project-[project].svelte @@ -2,16 +2,8 @@ import { afterNavigate } from '$app/navigation'; import { base } from '$app/paths'; import { page } from '$app/stores'; - import { CardGrid, Collapsible, CollapsibleItem } from '$lib/components'; - import { scopes } from '$lib/constants'; - import { - Button, - Form, - FormList, - InputChoice, - InputPassword, - InputText - } from '$lib/elements/forms'; + import { CardGrid, Secret } from '$lib/components'; + import { Button, Form, FormList, InputText } from '$lib/elements/forms'; import InputDateTime from '$lib/elements/forms/inputDateTime.svelte'; import { difference } from '$lib/helpers/array'; import { toLocaleDateTime } from '$lib/helpers/date'; @@ -21,39 +13,30 @@ import { sdkForConsole } from '$lib/stores/sdk'; import { onMount } from 'svelte'; import { project } from '../../../store'; + import Scopes from '../scopes.svelte'; import Delete from './delete.svelte'; import { key } from './store'; const projectId = $page.params.project; const keyId = $page.params.key; - const activeScopes = scopes.reduce((prev, next) => { - prev[next.scope] = false; - - return prev; - }, {}); let loaded = false; let showDelete = false; let name: string = null; let secret: string = null; let expire: string = null; + let scopes: string[] = null; onMount(handle); afterNavigate(handle); async function handle(event = null) { - const promise = key.load(projectId, keyId); - if ($key?.$id !== keyId) { - await promise; - } + await key.load(projectId, keyId); name ??= $key.name; secret ??= $key.secret; expire ??= $key.expire; - unselectAll(); - $key.scopes.forEach((scope) => { - activeScopes[scope] = true; - }); + scopes ??= $key.scopes; updateLayout({ navigate: event, @@ -120,13 +103,8 @@ async function updateScopes() { try { - await sdkForConsole.projects.updateKey( - $project.$id, - $key.$id, - $key.name, - selectedScoped - ); - $key.scopes = selectedScoped; + await sdkForConsole.projects.updateKey($project.$id, $key.$id, $key.name, scopes); + $key.scopes = scopes; addNotification({ type: 'success', message: 'API Key scopes has been updated' @@ -138,22 +116,6 @@ }); } } - - function selectAll() { - for (const scope in activeScopes) { - activeScopes[scope] = true; - } - } - - function unselectAll() { - for (const scope in activeScopes) { - activeScopes[scope] = false; - } - } - - $: selectedScoped = scopes - .filter((scope) => activeScopes[scope.scope]) - .map(({ scope }) => scope); @@ -162,13 +124,14 @@ {#if loaded} + {@const accessedAt = $key.accessedAt ? toLocaleDateTime($key.accessedAt) : 'never'}
    {$key.name}

    - Last accessed: {toLocaleDateTime($key.accessedAt)}
    + Last accessed: {accessedAt}
    Scopes granted: {$key.scopes.length}

    @@ -178,18 +141,9 @@
    API Key Secret
    - + - - - -
    @@ -220,35 +174,15 @@ practice to allow only the permissions you need to meet your project goals.

    -
    - - -
    - - {#each ['Authentication', 'Database', 'Functions', 'Storage', 'Other'] as category} - - {category} - - {#each scopes.filter((s) => s.category === category) as scope} - - {scope.description} - - {/each} - - - {/each} - +
    @@ -278,7 +212,7 @@
    {$key.name}
    -

    Last accessed: {toLocaleDateTime($key.accessedAt)}

    +

    Last accessed: {accessedAt}

    diff --git a/src/routes/console/project-[project]/overview/keys/create.svelte b/src/routes/console/project-[project]/overview/keys/create.svelte index 80765d20ca..043cae7cb7 100644 --- a/src/routes/console/project-[project]/overview/keys/create.svelte +++ b/src/routes/console/project-[project]/overview/keys/create.svelte @@ -1,32 +1,21 @@ - + Create API Key - {#each scopes as scope} - - {/each} + diff --git a/src/routes/console/project-[project]/overview/keys/scopes.svelte b/src/routes/console/project-[project]/overview/keys/scopes.svelte new file mode 100644 index 0000000000..d60f147308 --- /dev/null +++ b/src/routes/console/project-[project]/overview/keys/scopes.svelte @@ -0,0 +1,72 @@ + + +
    + + +
    + + {#each ['Authentication', 'Database', 'Functions', 'Storage', 'Other'] as category} + + {category} + + {#each allScopes.filter((s) => s.category === category) as scope} + + {scope.description} + + {/each} + + + {/each} + From aa098beb91ee3a860a225d8175cba2909cdb710c Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 5 Oct 2022 17:58:52 +0200 Subject: [PATCH 3/6] add: tests --- tests/unit/components/secret.test.ts | 46 ++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 tests/unit/components/secret.test.ts diff --git a/tests/unit/components/secret.test.ts b/tests/unit/components/secret.test.ts new file mode 100644 index 0000000000..5980bf226d --- /dev/null +++ b/tests/unit/components/secret.test.ts @@ -0,0 +1,46 @@ +import '@testing-library/jest-dom'; +import { vi } from 'vitest'; +import { render, fireEvent } from '@testing-library/svelte'; +import { Secret } from '../../../src/lib/components'; +import { tick } from 'svelte'; + +const value = 'This is a secret'; + +test('shows Secret component', () => { + const { container } = render(Secret, { value }); + const secret = container.querySelector('span.text'); + const toggle = container.querySelector('[aria-label="show hidden text"]'); + const copy = container.querySelector('[aria-label="copy text"]'); + + expect(secret).toBeInTheDocument(); + expect(toggle).toBeInTheDocument(); + expect(copy).toBeInTheDocument(); +}); + +test('toggle secret', async () => { + const { container } = render(Secret, { value }); + const toggle = container.querySelector('[aria-label="show hidden text"]'); + let secret = container.querySelector('span.text'); + expect(secret).not.toContainEqual(value); + await fireEvent.click(toggle); + secret = container.querySelector('span.text'); + expect(secret.textContent).toEqual(value); + await fireEvent.click(toggle); + secret = container.querySelector('span.text'); + expect(secret.textContent).not.toEqual(value); +}); + +test('copy to clipboard on click', async () => { + const { container } = render(Secret, { value }); + const copy = container.querySelector('[aria-label="copy text"]'); + + Object.assign(window.navigator, { + clipboard: { + writeText: vi.fn().mockImplementation(() => Promise.resolve()) + } + }); + + await fireEvent.click(copy); + + expect(window.navigator.clipboard.writeText).toHaveBeenCalledWith(value); +}); From 5e3f571c7aaab554edd4cccba1c1a7a330b2438b Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 5 Oct 2022 17:59:20 +0200 Subject: [PATCH 4/6] cleanup test file --- tests/unit/components/secret.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/unit/components/secret.test.ts b/tests/unit/components/secret.test.ts index 5980bf226d..7225ede9ad 100644 --- a/tests/unit/components/secret.test.ts +++ b/tests/unit/components/secret.test.ts @@ -2,7 +2,6 @@ import '@testing-library/jest-dom'; import { vi } from 'vitest'; import { render, fireEvent } from '@testing-library/svelte'; import { Secret } from '../../../src/lib/components'; -import { tick } from 'svelte'; const value = 'This is a secret'; @@ -20,12 +19,15 @@ test('shows Secret component', () => { test('toggle secret', async () => { const { container } = render(Secret, { value }); const toggle = container.querySelector('[aria-label="show hidden text"]'); + let secret = container.querySelector('span.text'); expect(secret).not.toContainEqual(value); await fireEvent.click(toggle); + secret = container.querySelector('span.text'); expect(secret.textContent).toEqual(value); await fireEvent.click(toggle); + secret = container.querySelector('span.text'); expect(secret.textContent).not.toEqual(value); }); From e6f5d00d60f4e829f05bdb862c7b069a6f5e7d7b Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Wed, 5 Oct 2022 18:00:47 +0200 Subject: [PATCH 5/6] fix: increase default secret --- src/lib/components/secret.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/secret.svelte b/src/lib/components/secret.svelte index 458005a93e..e44499b89e 100644 --- a/src/lib/components/secret.svelte +++ b/src/lib/components/secret.svelte @@ -9,7 +9,7 @@ {#if show} {value} {:else} - •••••• + •••••••••••• {/if}
    -
    10
    +
    XX
    Realtime Connections