Skip to content

Commit

Permalink
Merge pull request #3109 from opral/sherl-96-rework-test-sherlock-wor…
Browse files Browse the repository at this point in the history
…kspace-recommendation-feature

rework test sherlock workspace recommendation feature
  • Loading branch information
felixhaeberle authored Sep 10, 2024
2 parents 2bce435 + d5c7d6d commit 99649c5
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from "./recommendation.js"
import * as fs from "node:fs/promises"

// Mocking VSCode APIs
vi.mock("vscode", () => ({
resolveWebviewView: vi.fn(),
window: {
Expand All @@ -15,13 +16,14 @@ vi.mock("vscode", () => ({
},
WebviewView: class {
webview = {
asWebviewUri: (uri: vscode.Uri) => uri.toString(),
asWebviewUri: (uri: vscode.Uri) => (uri ? uri.toString() : "invalid-uri"),
options: {},
html: "",
onDidReceiveMessage: vi.fn(),
postMessage: vi.fn(),
cspSource: "",
}
onDidDispose = vi.fn()
},
commands: {
executeCommand: vi.fn(),
Expand All @@ -33,6 +35,7 @@ vi.mock("vscode", () => ({
Uri: {
file: vi.fn(),
joinPath: vi.fn((...args: string[]) => args.join("/")),
parse: vi.fn((uri: string) => ({ toString: () => uri })),
},
}))
vi.mock("node:path", () => ({
Expand All @@ -42,6 +45,16 @@ vi.mock("node:fs", () => ({
existsSync: vi.fn(),
readFileSync: vi.fn(),
}))
vi.mock("../../configuration.js", () => ({
CONFIGURATION: {
EVENTS: {
ON_DID_RECOMMENDATION_VIEW_CHANGE: {
event: vi.fn(),
fire: vi.fn(),
},
},
},
}))

describe("recommendationBannerView", () => {
beforeEach(() => {
Expand All @@ -68,7 +81,7 @@ describe("recommendationBannerView", () => {
})
})

describe("createRecommendationBanner", () => {
describe("createRecommendationView", () => {
const fakeWorkspaceFolder: vscode.WorkspaceFolder = {
uri: { fsPath: "/path/to/workspace" } as vscode.Uri,
name: "test-workspace",
Expand All @@ -83,26 +96,33 @@ describe("createRecommendationBanner", () => {
})
expect(typeof result.resolveWebviewView).toBe("function")
})
})

describe("createRecommendationBanner", () => {
const fakeWorkspaceFolder: vscode.WorkspaceFolder = {
uri: { fsPath: "/path/to/workspace" } as vscode.Uri,
name: "test-workspace",
index: 0,
}
it("should set up webview with scripts enabled and handle messages", async () => {
// @ts-expect-error
const webviewView = new vscode.WebviewView()
const mockContext = {} as vscode.ExtensionContext

it("should return an object with a resolveWebviewView function", () => {
const result = createRecommendationView({
const recommendationView = createRecommendationView({
fs: fs,
workspaceFolder: fakeWorkspaceFolder,
context: {} as vscode.ExtensionContext,
context: mockContext,
})

await recommendationView.resolveWebviewView(webviewView)

expect(webviewView.webview.options.enableScripts).toBe(true)

webviewView.webview.onDidReceiveMessage({
command: "addSherlockToWorkspace",
})

expect(webviewView.webview.onDidReceiveMessage).toHaveBeenCalledWith({
command: "addSherlockToWorkspace",
})
expect(typeof result.resolveWebviewView).toBe("function")
})
})

describe("getRecommendationBannerHtml", () => {
describe("getRecommendationViewHtml", () => {
const fakeWorkspaceFolder: vscode.WorkspaceFolder = {
uri: { fsPath: "/path/to/workspace" } as vscode.Uri,
name: "test-workspace",
Expand All @@ -116,9 +136,10 @@ describe("getRecommendationBannerHtml", () => {
it("should return html", async () => {
const args = {
webview: {
asWebviewUri: (uri: vscode.Uri) => (uri ? uri.toString() : ""),
asWebviewUri: (uri: vscode.Uri) => (uri ? uri.toString() : "invalid-uri"),
options: {},
html: "",
onDidDispose: vi.fn(),
onDidReceiveMessage: vi.fn(),
postMessage: vi.fn(),
cspSource: "self",
Expand All @@ -130,4 +151,25 @@ describe("getRecommendationBannerHtml", () => {
const result = await getRecommendationViewHtml(args)
expect(result).toContain(`<html lang="en">`)
})

it("should generate valid HTML structure with content", async () => {
const args = {
webview: {
asWebviewUri: (uri: vscode.Uri) => (uri ? uri.toString() : "invalid-uri"),
options: {},
html: "",
onDidReceiveMessage: vi.fn(),
postMessage: vi.fn(),
cspSource: "self",
} as unknown as vscode.Webview,
fs: {} as typeof fs,
workspaceFolder: fakeWorkspaceFolder,
context: {} as vscode.ExtensionContext,
}

const html = await getRecommendationViewHtml(args)
expect(html).toContain("To improve your i18n workflow:")
expect(html).toContain('<div class="container">')
expect(html).toContain('<html lang="en">')
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function createRecommendationView(args: {
switch (message.command) {
case "addSherlockToWorkspace":
if (args.workspaceFolder) {
Sherlock.add({
await Sherlock.add({
fs: args.fs,
workingDirectory: args.workspaceFolder.uri.fsPath,
})
Expand All @@ -35,26 +35,42 @@ export function createRecommendationView(args: {
}
})

webviewView.webview.html = await getRecommendationViewHtml({
webview: webviewView.webview,
workspaceFolder: args.workspaceFolder,
context: args.context,
fs: args.fs,
})
// Load the webview content initially
await updateRecommendationViewHtml(webviewView, args)

// Listen for updates and debounce rapid events
const debouncedUpdate = debounce(() => updateRecommendationViewHtml(webviewView, args), 300)

const disposableEvent = CONFIGURATION.EVENTS.ON_DID_RECOMMENDATION_VIEW_CHANGE.event(
async () => {
debouncedUpdate()
}
)

// Listen for updates
CONFIGURATION.EVENTS.ON_DID_RECOMMENDATION_VIEW_CHANGE.event(async () => {
webviewView.webview.html = await getRecommendationViewHtml({
webview: webviewView.webview,
workspaceFolder: args.workspaceFolder,
context: args.context,
fs: args.fs,
})
// Dispose the listener when the view is disposed
webviewView.onDidDispose(() => {
disposableEvent.dispose()
})
},
}
}

async function updateRecommendationViewHtml(
webviewView: vscode.WebviewView,
args: {
workspaceFolder: vscode.WorkspaceFolder
context: vscode.ExtensionContext
fs: FileSystem
}
) {
webviewView.webview.html = await getRecommendationViewHtml({
webview: webviewView.webview,
workspaceFolder: args.workspaceFolder,
context: args.context,
fs: args.fs,
})
}

export async function getRecommendationViewHtml(args: {
webview: vscode.Webview
workspaceFolder: vscode.WorkspaceFolder
Expand Down Expand Up @@ -215,3 +231,14 @@ export async function recommendationBannerView(args: {
})
)
}

const debounce = <T extends (...args: any[]) => void>(
fn: T,
delay: number
): ((...args: Parameters<T>) => void) => {
let timeout: NodeJS.Timeout
return (...args: Parameters<T>) => {
clearTimeout(timeout)
timeout = setTimeout(() => fn(...args), delay)
}
}

0 comments on commit 99649c5

Please sign in to comment.