Skip to content
This repository has been archived by the owner on Mar 22, 2024. It is now read-only.

Commit

Permalink
feat: list paper sizes supported by a specific printer (#447)
Browse files Browse the repository at this point in the history
* types: defined all printer properties; defined default printer properties

* feat(windows-printer-valid): support for build multiple printer properties

* feat(getDefaultPrinter): support for optional custom printer properties

* feat(getPrinters): support for optional custom printer properties

* test: added test for custom printer properties

* fix: prettier spaces

* feat(README.md): getPrinters with custom properties example

* fix: printer type with fixed 'deviceId' and 'name' property

* chore: npm install

* fix(isValidPrinter): test not covering, change properties param to required

* Revert "feat(README.md): getPrinters with custom properties example"
because the property 'printerPaperNames' will be default

This reverts commit fa91131.

* fix(type Printer): only support 'printerPaperNames' for now; get rid of the rest properties

* fix(defaultProperties): add 'printerPaperNames'

* test(get-default-printer): removed unsupported properties

* feat(windows-printer-valid): always return paperSizes option

* feat(windows-printer-valid): support for custom keys mapping

* fix(getPrinters, getDefaultPrinter): removed properties argument

* fix(index): fixed paperSizes in printer type; export const properties

* fix(tests): add key `paperSizes` to all assertions

* fix(printers): removed extra spaces

* test: better stdout examples

* fix(properties): transform from array to object mapping

* fix(properties): removed dynamic `properties` to `Get-CimInstance` command
  • Loading branch information
smallsoft-gustavo authored Mar 7, 2023
1 parent b5eda9b commit 7f3d331
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 37 deletions.
21 changes: 7 additions & 14 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 30 additions & 2 deletions src/get-default-printer/get-default-printer.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { mocked } from "jest-mock";
import getDefaultPrinter, { Printer } from "./get-default-printer";
import getDefaultPrinter from "./get-default-printer";
import execAsync from "../utils/exec-file-async";
import { Printer } from "..";

jest.mock("../utils/throw-if-unsupported-os");
jest.mock("../utils/exec-file-async");
Expand All @@ -26,11 +27,12 @@ it("gets the default printer", async () => {
stderr: "",
});

const result: Printer = await getDefaultPrinter();
const result: Printer | null = await getDefaultPrinter();

expect(result).toStrictEqual({
deviceId: "Microsoft Print to PDF",
name: "Microsoft Print to PDF",
paperSizes: [],
});
});

Expand Down Expand Up @@ -62,3 +64,29 @@ it("throws when execAsync fails", () => {
mockedExecAsync.mockRejectedValue("error");
return expect(getDefaultPrinter()).rejects.toBe("error");
});

it("gets the default printer with custom and repeated properties", async () => {
const stdout = `
Name : Microsoft Print to PDF
Caption : Microsoft Print to PDF
DeviceID : Microsoft Print to PDF
PaperSizesSupported : {1, 1, 1, 1...}
PortName : USB001
PrinterPaperNames : {A4, 144mm x 100mm}
`;

mockedExecAsync.mockResolvedValue({
stdout,
stderr: "",
});

const result: Printer | null = await getDefaultPrinter();

expect(result).toStrictEqual({
deviceId: "Microsoft Print to PDF",
name: "Microsoft Print to PDF",
paperSizes: ["A4", "144mm x 100mm"],
});
});
8 changes: 2 additions & 6 deletions src/get-default-printer/get-default-printer.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
import execFileAsync from "../utils/exec-file-async";
import throwIfUnsupportedOperatingSystem from "../utils/throw-if-unsupported-os";
import isValidPrinter from "../utils/windows-printer-valid";

export interface Printer {
deviceId: string;
name: string;
}
import { Printer } from "..";

async function getDefaultPrinter(): Promise<Printer | null> {
try {
throwIfUnsupportedOperatingSystem();

const { stdout } = await execFileAsync("Powershell.exe", [
"-Command",
"Get-CimInstance Win32_Printer -Property DeviceID,Name -Filter Default=true",
`Get-CimInstance Win32_Printer -Property DeviceID,Name,PrinterPaperNames -Filter Default=true`,
]);

const printer = stdout.trim();
Expand Down
36 changes: 34 additions & 2 deletions src/get-printers/get-printers.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { mocked } from "jest-mock";
import { Printer } from "../get-default-printer/get-default-printer";
import { Printer } from "..";
import execAsync from "../utils/exec-file-async";
import getPrinters from "./get-printers";

Expand Down Expand Up @@ -70,18 +70,21 @@ it("returns list of available printers", async () => {
const result: Printer[] = await getPrinters();

expect(result).toStrictEqual([
{ deviceId: "OneNote", name: "OneNote" },
{ deviceId: "OneNote", name: "OneNote", paperSizes: [] },
{
deviceId: "Microsoft-XPS-Document-Writer",
name: "Microsoft XPS Document Writer",
paperSizes: [],
},
{
deviceId: "Microsoft_Print_to_PDF",
name: "Microsoft Print to PDF",
paperSizes: [],
},
{
deviceId: "Fax",
name: "Fax",
paperSizes: [],
},
]);
});
Expand All @@ -106,3 +109,32 @@ it("fails with an error", () => {
mockedExecAsync.mockRejectedValue("error");
return expect(getPrinters()).rejects.toBe("error");
});

it("returns list of available printers with custom properties", async () => {
const stdout = `
Status : Unknown
Name : Canon Printer
Caption : Canon Printer
DeviceID : Canon-Printer
PaperSizesSupported : {1, 1, 1, 1...}
PortName : USB001
PrinterPaperNames : {A4, 144mm x 100mm, 2 x 4, 4 x 4...}
`;

mockedExecAsync.mockResolvedValue({
stdout,
stderr: "",
});

const result: Printer[] = await getPrinters();

expect(result).toStrictEqual([
{
deviceId: "Canon-Printer",
name: "Canon Printer",
paperSizes: ["A4", "144mm x 100mm", "2 x 4", "4 x 4"],
},
]);
});
4 changes: 2 additions & 2 deletions src/get-printers/get-printers.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import execFileAsync from "../utils/exec-file-async";
import isValidPrinter from "../utils/windows-printer-valid";
import throwIfUnsupportedOperatingSystem from "../utils/throw-if-unsupported-os";
import { Printer } from "../get-default-printer/get-default-printer";
import { Printer } from "..";

async function getPrinters(): Promise<Printer[]> {
function stdoutHandler(stdout: string) {
Expand All @@ -26,7 +26,7 @@ async function getPrinters(): Promise<Printer[]> {
throwIfUnsupportedOperatingSystem();
const { stdout } = await execFileAsync("Powershell.exe", [
"-Command",
"Get-CimInstance Win32_Printer -Property DeviceID,Name",
`Get-CimInstance Win32_Printer -Property DeviceID,Name,PrinterPaperNames`,
]);
return stdoutHandler(stdout);
} catch (error) {
Expand Down
7 changes: 6 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,9 @@ export { default as print } from "./print/print";
export { default as getPrinters } from "./get-printers/get-printers";
export { default as getDefaultPrinter } from "./get-default-printer/get-default-printer";
export { PrintOptions } from "./print/print";
export { Printer } from "./get-default-printer/get-default-printer";

export type Printer = {
deviceId: string;
name: string;
paperSizes: string[];
};
38 changes: 29 additions & 9 deletions src/utils/windows-printer-valid.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { Printer } from "../get-default-printer/get-default-printer";
import { Printer } from "../index";

// map windows-printer key to final printerData key
const properties: { [key: string]: keyof Printer } = {
DeviceID: "deviceId",
Name: "name",
PrinterPaperNames: "paperSizes",
};

export default function isValidPrinter(printer: string): {
isValid: boolean;
Expand All @@ -7,22 +14,35 @@ export default function isValidPrinter(printer: string): {
const printerData: Printer = {
deviceId: "",
name: "",
paperSizes: [],
};

const isValid = printer.split(/\r?\n/).some((line) => {
const [label, value] = line.split(":").map((el) => el.trim());
printer.split(/\r?\n/).forEach((line) => {
let [label, value] = line.split(":").map((el) => el.trim());

const lowerLabel = label.toLowerCase();
// handle array dots
if (value.match(/^{(.*)(\.{3})}$/)) {
value = value.replace("...}", "}");
}

// @ts-ignore
if (lowerLabel === "deviceid") printerData.deviceId = value;
// handle array returns
const matches = value.match(/^{(.*)}$/);

// @ts-ignore
if (lowerLabel === "name") printerData.name = value;
if (matches && matches[1]) {
// @ts-ignore
value = matches[1].split(", ");
}

const key = properties[label];

return !!(printerData.deviceId && printerData.name);
if (key === undefined) return;

// @ts-ignore
printerData[key] = value;
});

const isValid = !!(printerData.deviceId && printerData.name);

return {
isValid,
printerData,
Expand Down
2 changes: 1 addition & 1 deletion webpack.production.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ module.exports = {
},
plugins: [
new CleanWebpackPlugin(),
new CopyPlugin({patterns: [{ from: "./src/SumatraPDF-3.4.6-32.exe" }]}),
new CopyPlugin({ patterns: [{ from: "./src/SumatraPDF-3.4.6-32.exe" }] }),
],
target: "node",
node: {
Expand Down

0 comments on commit 7f3d331

Please sign in to comment.