Moled Dataset using Pex and Moles - moles

I want to test below method.I am returning dataset and checking table collection.
public string FetchAllDetails(string useCase, string strMainFlow)
{
var strError = new StringBuilder();
DataSet ds = _dal.Fetchdetails(useCase, strMainFlow, useCaseId, useCaseName);
DataTable dt = new DataTable();
dt = ds.Tables[0];
if (dt.Rows.Count > 0)
{
BindUsecaseId(strError, useCaseName);
foreach (var row in ds.Tables[0].AsEnumerable())
BindError(strError, GetOriginalFieldName(row[0].ToString()));
}
return strError.ToString();
}
I wrote below unit test using Pex.
[PexMethod]
public string FetchAllDetailsTest(string useCase, string strMainFlow)
{
SIUploadtoolDAL dal = new SIUploadtoolDAL();
UploadtoolBL target = new UploadtoolBL(dal);
MDataTableCollection dt2 = new MDataTableCollection();
dt2.Add = () =>
{
MDataTable dt1 = new MDataTable();
dt1.ColumnsGet = () =>
{
MDataColumnCollection dcCollection = new MDataColumnCollection();
dcCollection.Add = () =>
{
MDataColumn dc = new MDataColumn();
dc.ColumnNameGet = () =>
{
return "string";
};
dc.DataTypeGet = () =>
{
return typeof(string);
};
return dc;
};
return dcCollection;
};
return dt1;
};
dal.FetchdetailsStringStringInt32StringSqlTransaction = (useCaselocal, strMainFlowlocal, useCaseIdlocal, useCaseNamelocal) =>
{
MDataSet ds = new MDataSet();
ds.TablesGet = () =>
{
MDataTableCollection dt = new MDataTableCollection();
dt.Add = () =>
{
MDataTable dt1 = new MDataTable();
dt1.ColumnsGet = () =>
{
MDataColumnCollection dcCollection = new MDataColumnCollection();
dcCollection.Add = () =>
{
MDataColumn dc = new MDataColumn();
dc.ColumnNameGet = () =>
{
return "string";
};
dc.DataTypeGet = () =>
{
return typeof(string);
};
return dc;
};
return dcCollection;
};
return dt1;
};
return dt;
};
return ds;
};
return target.FetchAllDetails(useCase, strMainFlow, useCaseId, useCaseName);
}
Now I am getting MoledNotImplemented for DataTablecollection error.
How I can moled dataset tabele collection?

Related

How to mock ExecuteReaderAsync in .NET Framework c#

I need to mock the ExecuteReaderAsync for my project.
Actually in my project I am dealing all the db related query using procedure so that I have created generic repo to handle the db query using the below code.
Below one is the repository to make the db connection and execute the stored procedure .
public async Task<DbDataReader> ExecGetWithStoreProcedure(string storeProcedureName, params object[] parameters)
{
try
{
var command = _dbContext.Database.Connection.CreateCommand();
command.Connection.Open();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = storeProcedureName;
foreach (var item in parameters)
{
command.Parameters.Add(item);
}
return await command.ExecuteReaderAsync().ConfigureAwait(false);
}
catch (Exception ex)
{
throw ex;
}
}
Now when I am writing the test case so noticed that DB is not getting mock it's returning the actual data from database. I have tried to mock the DbCommand , DbDataReader but still not able to mock it successfully. Here is the below code
Below one is the service class.
public async Task<HttpResponseModel<FormulationReviewCommentsResults>> GetDashboardFormulationReviewComments(int PageSize, int PageNumber, string userName)
{
List<Tbl_FormulationReviewComments> list = new List<Tbl_FormulationReviewComments>();
var result = new FormulationReviewCommentsResults();
try
{
using (_unitOfWork = new UnitOfWorkRMM(new PlutoContextRMM(DBConstants.connectionName)))
{
var reader = await _unitOfWork.DashboardRepos.ExecGetWithStoreProcedure(DBConstants.USP_MST_GET_DashboardReviewComments,
new SqlParameter(DBConstants.PageSize, SqlDbType.Int) { SqlValue = PageSize },
new SqlParameter(DBConstants.PageNumber, SqlDbType.Int) { SqlValue = PageNumber },
new SqlParameter(DBConstants.userName, SqlDbType.NVarChar) { SqlValue = userName }).ConfigureAwait(false);
while (reader.Read())
{
var comments = new Tbl_FormulationReviewComments();
comments.Id = int.Parse(reader.GetValue(0).ToString());
comments.Name = reader.GetValue(1).ToString();
comments.FormulationDetailId = int.Parse(reader.GetValue(2).ToString());
comments.Comment = reader.GetValue(3).ToString();
comments.FormulationDetailId = int.Parse(reader.GetValue(4).ToString());
comments.FormulationReferenceNo = reader.GetValue(5).ToString();
comments.VersionNo =reader.GetValue(6).ToString();
comments.TotalRecords = int.Parse(reader.GetValue(7).ToString());
list.Add(comments);
}
result.FormulationReviewComments = list;
result.TotalRecords = list.Count > 0 ? list[0].TotalRecords : 0;
return _httpResponse.HandleReturnResponse(result, MessagesConstants.CommonErrorMessage, false);
}
}
catch (Exception ex)
{
_logger.Error(ex, strLoggerName);
return _httpResponse.HandleReturnResponse(result, MessagesConstants.CommonErrorMessage, false);
}
}
Mocking the DataReader and all realted things using the below code.
public static void GetDashBoard3()
{
string[] fieldNames = { "Id", "Name", "FormulationDetailId", "Comment", "FormulationDetailId", "FormulationReferenceNo", "VersionNo", "TotalRecords" };
List<FormulationReviewCommentsResults> resultModel = new List<FormulationReviewCommentsResults>();
List<Tbl_FormulationReviewComments> items = new List<Tbl_FormulationReviewComments>();
items.Add(new Tbl_FormulationReviewComments
{
TotalRecords = 1,
Comment = "",
CommentAssignedTo = "",
CommentClosedBy = "",
CommentClosedDate = DateTime.Now,
CommentCreatedBy = "",
CommentCreatedDate = DateTime.Now,
CommentDueDate = DateTime.Now,
CommentRepliedBy = "",
CommentRepliedDate = DateTime.Now,
CommentsReplied = "",
CommentUpdatedBy = "",
CommentUpdatedDate = DateTime.Now,
CreatedBy = "",
CreatedDate = DateTime.Now,
FormulationDetailId = 12313,
FormulationRawMaterialId = 123,
FormulationRawMaterialSubComponentId = 12321,
FormulationReferenceNo = "",
Id = 1,
isClosed = false,
IsDeleted = false,
isReplied = false,
ManufacturerId = 123,
ManufacturerName = "",
MarketId = 123,
MarketName = "",
Name = "",
RawMaterialId = 123,
RawMaterialName = "",
RegulationId = 123,
ReviewComments = "sdfsadf",
ReviewedBy = "",
ReviewedDate = DateTime.Now,
StatusCode = "202",
StatusId = 1,
StatusName = "",
SubComponentName = "",
SupplierId = 1,
SupplierName = "",
SupplierRawMaterialSubComponentDetailId = 123,
TradeName = "",
});
resultModel.Add(new FormulationReviewCommentsResults
{
FormulationReviewComments = items,
TotalRecords = 1
});
Mock<DbProviderFactory> mockedDataReader = new Mock<DbProviderFactory>();
var commandMock = new Mock<IDbCommand>();
var readerMock = new Mock<IDataReader>();
commandMock.Setup(m => m.ExecuteReader()).Returns(readerMock.Object).Verifiable();
var parameterMock = new Mock<IDbDataParameter>();
commandMock.Setup(m => m.CreateParameter()).Returns(parameterMock.Object);
commandMock.Setup(m => m.Parameters.Add(It.IsAny<IDbDataParameter>())).Verifiable();
commandMock.Setup(m => m.Parameters.Add(It.IsAny<IDbDataParameter>())).Verifiable();
commandMock.Setup(m => m.Parameters.Add(It.IsAny<IDbDataParameter>())).Verifiable();
var connectionMock = new Mock<IDbConnection>();
connectionMock.Setup(m => m.CreateCommand()).Returns(commandMock.Object);
//-----------------------------------------------------
readerMock.Setup(x => x.Read()).Returns(() => true);
readerMock.Setup(x => x.FieldCount).Returns(8);
readerMock.Setup(m => m.GetName(0)).Returns("id"); // the first column name
readerMock.Setup(m => m.GetName(1)).Returns("Name");
readerMock.Setup(m => m.GetName(2)).Returns("FormulationDetailId");
readerMock.Setup(m => m.GetName(3)).Returns("Comment");
readerMock.Setup(m => m.GetName(4)).Returns("FormulationDetailId");
readerMock.Setup(m => m.GetName(5)).Returns("FormulationReferenceNo");
readerMock.Setup(m => m.GetName(6)).Returns("VersionNo");
readerMock.Setup(m => m.GetName(7)).Returns("TotalRecords");
readerMock.Setup(x => x.GetValue(0)).Returns((int id) => resultModel[0].FormulationReviewComments[0].Id);
readerMock.Setup(x => x.GetValue(1)).Returns((string Name) => resultModel[0].FormulationReviewComments[0].Name);
readerMock.Setup(x => x.GetValue(2)).Returns((int FormulationDetailId) => resultModel[0].FormulationReviewComments[0].FormulationDetailId);
readerMock.Setup(x => x.GetValue(3)).Returns((string Comment) => resultModel[0].FormulationReviewComments[0].Comment);
readerMock.Setup(x => x.GetValue(4)).Returns((int FormulationDetailId) => resultModel[0].FormulationReviewComments[0].FormulationDetailId);
readerMock.Setup(x => x.GetValue(5)).Returns((string FormulationReferenceNo) => resultModel[0].FormulationReviewComments[0].FormulationReferenceNo);
readerMock.Setup(x => x.GetValue(6)).Returns((string VersionNo) => resultModel[0].FormulationReviewComments[0].VersionNo);
readerMock.Setup(x => x.GetValue(7)).Returns((int TotalRecords) => resultModel[0].FormulationReviewComments[0].TotalRecords);
readerMock.SetupSequence(m => m.Read()).Returns(true).Returns(false);
}
Here is the final unit test cases for the above
[Theory]
[InlineData(1, 1, "asdf")]
public async Task GetDashboardFormulationReviewComments1New(int a, int b, string c)
{
//var dd = (DbDataReader)dataReader;
DashboardReposReturns.GetDashBoard3();
var context2 = _unitOfWork.Setup(dd => dd.DashboardRepos.ExecGetWithStoreProcedure(It.IsAny<string>()));
// Act
var result = await _dashboardRepos.GetDashboardFormulationReviewComments(a, b, c);
//Assert
Assert.NotNull(result);
Assert.NotNull(result.Data);
Assert.True(result.Data.TotalRecords == 0);
}

this doesn't work for me SESSION_STORAGE:

I am trying to create a new session to have the session in a database, Postgres. I am trying to use this code, but nothing works, and it is frustrating.
I'm almost sure that I need to send a second argument, but I don't know what it will be!.
my code:
Shopify.Context.initialize({
API_KEY: process.env.SHOPIFY_API_KEY,
API_SECRET_KEY: process.env.SHOPIFY_API_SECRET,
SCOPES: process.env.SCOPES.split(","),
HOST_NAME: process.env.HOST.replace(/https:\/\//, ""),
API_VERSION: ApiVersion.April22,
IS_EMBEDDED_APP: true,
// This should be replaced with your preferred storage strategy
SESSION_STORAGE: new Shopify.Session.PostgreSQLSessionStorage(
new URL(process.env.DATABASE_URL)
),
});
error:
┃ file:///Users/blablabla/Documents/Apps/cli_shopify_mayo2022/cli-19may/server/middleware/verify-request.js:25
┃ if (session?.isActive()) {
┃ ^
┃
┃ TypeError: session?.isActive is not a function
┃ at file:///Users/diegotorres/Documents/Apps/cli_shopify_mayo2022/cli-19may/server/middleware/verify-request.js:25:18
┃ at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
┃
┃ Node.js v18.0.0
┃ [nodemon] app crashed - waiting for file changes before starting...
postgres file
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PostgreSQLSessionStorage = void 0;
var tslib_1 = require("tslib");
var pg_1 = tslib_1.__importDefault(require("pg"));
var session_utils_1 = require("../session-utils");
var defaultPostgreSQLSessionStorageOptions = {
sessionTableName: 'shopify_sessions',
port: 3211,
};
var PostgreSQLSessionStorage = /** #class */ (function () {
function PostgreSQLSessionStorage(dbUrl, opts) {
if (opts === void 0) { opts = {}; }
this.dbUrl = dbUrl;
if (typeof this.dbUrl === 'string') {
this.dbUrl = new URL(this.dbUrl);
}
this.options = tslib_1.__assign(tslib_1.__assign({}, defaultPostgreSQLSessionStorageOptions), opts);
this.ready = this.init();
}
PostgreSQLSessionStorage.withCredentials = function (host, dbName, username, password, opts) {
return new PostgreSQLSessionStorage(new URL("postgres://".concat(encodeURIComponent(username), ":").concat(encodeURIComponent(password), "#").concat(host, "/").concat(encodeURIComponent(dbName))), opts);
};
PostgreSQLSessionStorage.prototype.storeSession = function (session) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var entries, query;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.ready];
case 1:
_a.sent();
entries = (0, session_utils_1.sessionEntries)(session);
query = "\n INSERT INTO ".concat(this.options.sessionTableName, "\n (").concat(entries.map(function (_a) {
var _b = tslib_1.__read(_a, 1), key = _b[0];
return key;
}).join(', '), ")\n VALUES (").concat(entries.map(function (_, i) { return "$".concat(i + 1); }).join(', '), ")\n ON CONFLICT (id) DO UPDATE SET ").concat(entries
.map(function (_a) {
var _b = tslib_1.__read(_a, 1), key = _b[0];
return "".concat(key, " = Excluded.").concat(key);
})
.join(', '), ";\n ");
return [4 /*yield*/, this.query(query, entries.map(function (_a) {
var _b = tslib_1.__read(_a, 2), _key = _b[0], value = _b[1];
return value;
}))];
case 2:
_a.sent();
return [2 /*return*/, true];
}
});
});
};
PostgreSQLSessionStorage.prototype.loadSession = function (id) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var query, rows, rawResult;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.ready];
case 1:
_a.sent();
query = "\n SELECT * FROM ".concat(this.options.sessionTableName, "\n WHERE id = $1;\n ");
return [4 /*yield*/, this.query(query, [id])];
case 2:
rows = _a.sent();
if (!Array.isArray(rows) || (rows === null || rows === void 0 ? void 0 : rows.length) !== 1)
return [2 /*return*/, undefined];
rawResult = rows[0];
return [2 /*return*/, (0, session_utils_1.sessionFromEntries)(Object.entries(rawResult))];
}
});
});
};
PostgreSQLSessionStorage.prototype.deleteSession = function (id) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var query;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.ready];
case 1:
_a.sent();
query = "\n DELETE FROM ".concat(this.options.sessionTableName, "\n WHERE id = $1;\n ");
return [4 /*yield*/, this.query(query, [id])];
case 2:
_a.sent();
return [2 /*return*/, true];
}
});
});
};
PostgreSQLSessionStorage.prototype.disconnect = function () {
return this.client.end();
};
PostgreSQLSessionStorage.prototype.init = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
this.client = new pg_1.default.Client({ connectionString: this.dbUrl.toString() });
return [4 /*yield*/, this.connectClient()];
case 1:
_a.sent();
return [4 /*yield*/, this.createTable()];
case 2:
_a.sent();
return [2 /*return*/];
}
});
});
};
PostgreSQLSessionStorage.prototype.connectClient = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.client.connect()];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
PostgreSQLSessionStorage.prototype.hasSessionTable = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var query, _a, rows;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
query = "\n SELECT * FROM pg_catalog.pg_tables WHERE tablename = $1\n ";
return [4 /*yield*/, this.query(query, [this.options.sessionTableName])];
case 1:
_a = tslib_1.__read.apply(void 0, [_b.sent(), 1]), rows = _a[0];
return [2 /*return*/, Array.isArray(rows) && rows.length === 1];
}
});
});
};
PostgreSQLSessionStorage.prototype.createTable = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var hasSessionTable, query;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.hasSessionTable()];
case 1:
hasSessionTable = _a.sent();
if (!!hasSessionTable) return [3 /*break*/, 3];
query = "\n CREATE TABLE ".concat(this.options.sessionTableName, " (\n id varchar(255) NOT NULL PRIMARY KEY,\n shop varchar(255) NOT NULL,\n state varchar(255) NOT NULL,\n isOnline boolean NOT NULL,\n scope varchar(255),\n accessToken varchar(255)\n )\n ");
return [4 /*yield*/, this.query(query)];
case 2:
_a.sent();
_a.label = 3;
case 3: return [2 /*return*/];
}
});
});
};
PostgreSQLSessionStorage.prototype.query = function (sql, params) {
if (params === void 0) { params = []; }
return tslib_1.__awaiter(this, void 0, void 0, function () {
var result;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.client.query(sql, params)];
case 1:
result = _a.sent();
return [2 /*return*/, result.rows];
}
});
});
};
return PostgreSQLSessionStorage;
}());
exports.PostgreSQLSessionStorage = PostgreSQLSessionStorage;
so, investigating a bit I found the following file which is where the app breaks
import { Shopify } from "#shopify/shopify-api";
const TEST_GRAPHQL_QUERY = `
{
shop {
name
}
}`;
export default function verifyRequest(app, { returnHeader = true } = {}) {
return async (req, res, next) => {
const session = await Shopify.Utils.loadCurrentSession(
req,
res,
app.get("use-online-tokens")
);
let shop = req.query.shop;
if (session && shop && session.shop !== shop) {
// The current request is for a different shop. Redirect gracefully.
return res.redirect(`/auth?shop=${shop}`);
}
if (session?.isActive()) {
try {
// make a request to make sure oauth has succeeded, retry otherwise
const client = new Shopify.Clients.Graphql(
session.shop,
session.accessToken
);
await client.query({ data: TEST_GRAPHQL_QUERY });
return next();
} catch (e) {
if (
e instanceof Shopify.Errors.HttpResponseError &&
e.response.code === 401
) {
// We only want to catch 401s here, anything else should bubble up
} else {
throw e;
}
}
}
if (returnHeader) {
if (!shop) {
if (session) {
shop = session.shop;
} else if (Shopify.Context.IS_EMBEDDED_APP) {
const authHeader = req.headers.authorization;
const matches = authHeader?.match(/Bearer (.*)/);
if (matches) {
const payload = Shopify.Utils.decodeSessionToken(matches[1]);
shop = payload.dest.replace("https://", "");
}
}
}
if (!shop || shop === "") {
return res
.status(400)
.send(
`Could not find a shop to authenticate with. Make sure you are making your XHR request with App Bridge's authenticatedFetch method.`
);
}
res.status(403);
res.header("X-Shopify-API-Request-Failure-Reauthorize", "1");
res.header(
"X-Shopify-API-Request-Failure-Reauthorize-Url",
`/auth?shop=${shop}`
);
res.end();
} else {
res.redirect(`/auth?shop=${shop}`);
}
};
}
You should use cloneSession from Session
Here is full code from my working project and custom implimentation of postgresql session
// tslint:disable-next-line:no-submodule-imports
import { Session } from '#shopify/shopify-api/dist/auth/session/index.js';
import pg from 'pg';
// tslint:disable-next-line:interface-name
interface SessionInterface {
readonly id: string;
shop: string;
state: string;
isOnline: boolean;
scope?: string;
expires?: Date;
accessToken?: string;
onlineAccessInfo?: any;
isActive(): boolean;
}
// tslint:disable-next-line:interface-name
interface SessionStorage {
/**
* Creates or updates the given session in storage.
*
* #param session Session to store
*/
storeSession(session: SessionInterface): Promise<boolean>;
/**
* Loads a session from storage.
*
* #param id Id of the session to load
*/
loadSession(id: string): Promise<SessionInterface | undefined>;
/**
* Deletes a session from storage.
*
* #param id Id of the session to delete
*/
deleteSession(id: string): Promise<boolean>;
}
function fromEntries<T>(entries: Array<[keyof T, T[keyof T]]>): T {
return entries.reduce(
(acc, [key, value]) => ({ ...acc, [key]: value }),
<T>{}
);
}
function sessionFromEntries(
entries: Array<[string, string | number]>,
): SessionInterface {
const obj = fromEntries(
entries
// tslint:disable-next-line:variable-name
.filter(([_key, value]) => value !== null)
.map(([key, value]) => {
switch (key.toLowerCase()) {
case 'isonline':
return ['isOnline', value];
case 'accesstoken':
return ['accessToken', value];
default:
return [key.toLowerCase(), value];
}
}),
) as any;
if (typeof obj.isOnline === 'string') {
obj.isOnline = obj.isOnline.toString().toLowerCase() === 'true';
} else if (typeof obj.isOnline === 'number') {
obj.isOnline = Boolean(obj.isOnline);
}
if (obj.scope) { obj.scope = obj.scope.toString(); }
return obj;
}
const includedKeys = [
'id',
'shop',
'state',
'isOnline',
'scope',
'accessToken',
];
function sessionEntries(
session: SessionInterface,
): Array<[string, string | number]> {
return Object.entries(session).filter(([key]) => includedKeys.includes(key));
}
// tslint:disable-next-line:interface-name
interface PostgreSQLSessionStorageOptions {
sessionTableName: string;
port: number;
}
const defaultPostgreSQLSessionStorageOptions: PostgreSQLSessionStorageOptions =
{
sessionTableName: 'shopify_sessions',
port: 3211,
};
export class PostgreSQLSessionStorage implements SessionStorage {
public static withCredentials(
host: string,
dbName: string,
username: string,
password: string,
opts: Partial<PostgreSQLSessionStorageOptions>,
) {
return new PostgreSQLSessionStorage(
new URL(
`postgres://${encodeURIComponent(username)}:${encodeURIComponent(
password,
)}#${host}/${encodeURIComponent(dbName)}`,
),
opts,
);
}
public readonly ready: Promise<void>;
private options: PostgreSQLSessionStorageOptions;
private client: pg.Client;
constructor(
private dbUrl: URL,
opts: Partial<PostgreSQLSessionStorageOptions> = {},
) {
if (typeof this.dbUrl === 'string') {
this.dbUrl = new URL(this.dbUrl);
}
this.options = {...defaultPostgreSQLSessionStorageOptions, ...opts};
this.ready = this.init();
}
public async storeSession(session: SessionInterface): Promise<boolean> {
await this.ready;
const entries = sessionEntries(session);
const query = `
INSERT INTO ${this.options.sessionTableName}
(${entries.map(([key]) => key).join(', ')})
VALUES (${entries.map((_, i) => `$${i + 1}`).join(', ')})
ON CONFLICT (id) DO UPDATE SET ${entries
.map(([key]) => `${key} = Excluded.${key}`)
.join(', ')};
`;
await this.query(
query,
// tslint:disable-next-line:variable-name
entries.map(([_key, value]) => value),
);
return true;
}
public async loadSession(id: string): Promise<Session | undefined> {
await this.ready;
const query = `
SELECT * FROM ${this.options.sessionTableName}
WHERE id = $1;
`;
const rows = await this.query(query, [id]);
if (!Array.isArray(rows) || rows?.length !== 1) { return undefined; }
const rawResult = rows[0] as any;
const sessionData = sessionFromEntries(Object.entries(rawResult));
return Session.cloneSession(sessionData, sessionData.id);
}
public async deleteSession(id: string): Promise<boolean> {
await this.ready;
const query = `
DELETE FROM ${this.options.sessionTableName}
WHERE id = $1;
`;
await this.query(query, [id]);
return true;
}
public disconnect(): Promise<void> {
return this.client.end();
}
private async init() {
this.client = new pg.Client({connectionString: this.dbUrl.toString(), ssl: true});
await this.connectClient();
await this.createTable();
}
private async connectClient(): Promise<void> {
await this.client.connect();
}
private async hasSessionTable(): Promise<boolean> {
const query = `
SELECT * FROM pg_catalog.pg_tables WHERE tablename = $1
`;
const [rows] = await this.query(query, [this.options.sessionTableName]);
return Array.isArray(rows) && rows.length === 1;
}
private async createTable() {
const hasSessionTable = await this.hasSessionTable();
if (!hasSessionTable) {
const query = `
CREATE TABLE IF NOT EXISTS ${this.options.sessionTableName} (
id varchar(255) NOT NULL PRIMARY KEY,
shop varchar(255) NOT NULL,
state varchar(255) NOT NULL,
isOnline boolean NOT NULL,
scope varchar(255),
accessToken varchar(255)
)
`;
await this.query(query);
}
}
private async query(sql: string, params: any[] = []): Promise<any> {
const result = await this.client.query(sql, params);
return result.rows;
}
}

How do you create Expression<Func<T, T>> given the property names of T to map?

Here's what the required function would look like:
public static Expression<Func<T, T>> GetExpression<T>(string propertyNames) where T : class
{
var properties = propertyNames.Split(
new char[] { ',' },
StringSplitOptions.RemoveEmptyEntries
).ToList();
//need help here
}
Currently I'm doing it like this:
_context.Questions.Select(q =>
new Question() {
QuestionId = q.QuestionId,
QuestionEnglish = q.QuestionEnglish
}
).ToList();
And I want to replace it with:
_context.Questions.Select(GetExpression<Question>("QuestionId, QuestionInEnglish")).ToList();
Any help would be greatly appreciated.
You can do it like this;
public static Func<T, T> GetExpression<T>(string propertyNames)
{
var xParameter = Expression.Parameter(typeof(T), "parameter");
var xNew = Expression.New(typeof(T));
var selectFields = propertyNames.Split(',').Select(parameter => parameter.Trim())
.Select(parameter => {
var prop = typeof(T).GetProperty(parameter);
if (prop == null) // The field doesn't exist
{
return null;
}
var xOriginal = Expression.Property(xParameter, prop);
return Expression.Bind(prop, xOriginal);
}
).Where(x => x != null);
var lambda = Expression.Lambda<Func<T, T>>(Expression.MemberInit(xNew, selectFields), xParameter);
return lambda.Compile();
}
Usage;
var list = new List<Question>{new Question{QuestionEnglish = "QuestionName",QuestionId = 1}};
var result = list.Select(GetExpression<Question>("QuestionId, QuestionEnglish"));

chrome.serial receiveTimeout Not working.

Below code is a copy with minor edits from https://github.com/GoogleChrome/chrome-app-samples/tree/master/serial/ledtoggle. I am able to send a byte and receive a reply. I am not able to get an TimeoutError event in case of reply is not sent by the client. I have set timeout to 50 ms.
this.receiveTimeout = 50;
Entire code follows.
const DEVICE_PATH = 'COM1';
const serial = chrome.serial;
var ab2str = function(buf) {
var bufView = new Uint8Array(buf);
var encodedString = String.fromCharCode.apply(null, bufView);
return decodeURIComponent(escape(encodedString));
};
var str2ab = function(str) {
var encodedString = unescape((str));
var bytes = new Uint8Array(1);
bytes[0] = parseInt(encodedString);
}
return bytes.buffer;
};
var SerialConnection = function() {
this.connectionId = -1;
this.lineBuffer = "";
this.receiveTimeout =50;
this.boundOnReceive = this.onReceive.bind(this);
this.boundOnReceiveError = this.onReceiveError.bind(this);
this.onConnect = new chrome.Event();
this.onReadLine = new chrome.Event();
this.onError = new chrome.Event();
};
SerialConnection.prototype.onConnectComplete = function(connectionInfo) {
if (!connectionInfo) {
log("Connection failed.");
return;
}
this.connectionId = connectionInfo.connectionId;
chrome.serial.onReceive.addListener(this.boundOnReceive);
chrome.serial.onReceiveError.addListener(this.boundOnReceiveError);
this.onConnect.dispatch();
};
SerialConnection.prototype.onReceive = function(receiveInfo) {
if (receiveInfo.connectionId !== this.connectionId) {
return;
}
this.lineBuffer += ab2str(receiveInfo.data);
var index;
while ((index = this.lineBuffer.indexOf('$')) >= 0) {
var line = this.lineBuffer.substr(0, index + 1);
this.onReadLine.dispatch(line);
this.lineBuffer = this.lineBuffer.substr(index + 1);
}
};
SerialConnection.prototype.onReceiveError = function(errorInfo) {
log('Error');
if (errorInfo.connectionId === this.connectionId) {
log('Error');
this.onError.dispatch(errorInfo.error);
log('Error');
}
log('Error');
};
SerialConnection.prototype.connect = function(path) {
serial.connect(path, this.onConnectComplete.bind(this))
};
SerialConnection.prototype.send = function(msg) {
if (this.connectionId < 0) {
throw 'Invalid connection';
}
serial.send(this.connectionId, str2ab(msg), function() {});
};
SerialConnection.prototype.disconnect = function() {
if (this.connectionId < 0) {
throw 'Invalid connection';
}
serial.disconnect(this.connectionId, function() {});
};
var connection = new SerialConnection();
connection.onConnect.addListener(function() {
log('connected to: ' + DEVICE_PATH);
);
connection.onReadLine.addListener(function(line) {
log('read line: ' + line);
});
connection.onError.addListener(function() {
log('Error: ');
});
connection.connect(DEVICE_PATH);
function log(msg) {
var buffer = document.querySelector('#buffer');
buffer.innerHTML += msg + '<br/>';
}
document.querySelector('button').addEventListener('click', function() {
connection.send(2);
});
Maybe I'm reading the code incorrectly, but at no point do you pass receiveTimeout into chrome.serial. The method signature is chrome.serial.connect(string path, ConnectionOptions options, function callback), where options is an optional parameter. You never pass anything into options. Fix that and let us know what happens.

TypeError: 'undefined' is not a function (evaluating 'ime.registIMEKey()')

Despite of setting and defining everything in Samsung smart TV SDK 4.0 I am getting this error:
TypeError: 'undefined' is not a function (evaluating 'ime.registIMEKey()')
Please help!
CODE:
var widgetAPI = new Common.API.Widget();
var tvKey = new Common.API.TVKeyValue();
var wapal_magic =
{
elementIds: new Array(),
inputs: new Array(),
ready: new Array()
};
/////////////////////////
var Input = function (id, previousId, nextId) {
var previousElement = document.getElementById(previousId),
nextElement = document.getElementById(nextId);
var installFocusKeyCallbacks = function () {
ime.setKeyFunc(tvKey.KEY_UP, function (keyCode) {
previousElement.focus();
return false;
});
ime.setKeyFunc(tvKey.KEY_DOWN, function (keyCode) {
nextElement.focus();
return false;
});
ime.setKeyFunc(tvKey.KEY_RETURN, function (keyCode) {
widgetAPI.blockNavigation();
return false;
});
ime.setKeyFunc(tvKey.KEY_EXIT, function (keyCode) {
widgetAPI.blockNavigation();
return false;
});
}
var imeReady = function (imeObject) {
installFocusKeyCallbacks();
wapal_magic.ready(id);
},
ime = new IMEShell(id, imeReady, 'en'),
element = document.getElementById(id);
}
wapal_magic.createInputObjects = function () {
var index,
previousIndex,
nextIndex;
for (index in this.elementIds) {
previousIndex = index - 1;
if (previousIndex < 0) {
previousIndex = wapal_magic.inputs.length - 1;
}
nextIndex = (index + 1) % wapal_magic.inputs.length;
wapal_magic.inputs[index] = new Input(this.elementIds[index],
this.elementIds[previousIndex], this.elementIds[nextIndex]);
}
};
wapal_magic.ready = function (id) {
var ready = true,
i;
for (i in wapal_magic.elementIds) {
if (wapal_magic.elementIds[i] == id) {
wapal_magic.ready[i] = true;
}
if (wapal_magic.ready[i] == false) {
ready = false;
}
}
if (ready) {
document.getElementById("txtInp1").focus();
}
};
////////////////////////
wapal_magic.onLoad = function()
{
// Enable key event processing
//this.enableKeys();
// widgetAPI.sendReadyEvent();
this.initTextBoxes(new Array("txtInp1", "txtInp2"));
};
wapal_magic.initTextBoxes = function(textboxes){
this.elementIds = textboxes;
for(i=0;i<this.elementIds.length;i++){
this.inputs[i]=false;
this.ready[i]=null;
}
this.createInputObjects();
widgetAPI.registIMEKey();
};
wapal_magic.onUnload = function()
{
};
wapal_magic.enableKeys = function()
{
document.getElementById("anchor").focus();
};
wapal_magic.keyDown = function()
{
var keyCode = event.keyCode;
alert("Key pressed: " + keyCode);
switch(keyCode)
{
case tvKey.KEY_RETURN:
case tvKey.KEY_PANEL_RETURN:
alert("RETURN");
widgetAPI.sendReturnEvent();
break;
case tvKey.KEY_LEFT:
alert("LEFT");
break;
case tvKey.KEY_RIGHT:
alert("RIGHT");
break;
case tvKey.KEY_UP:
alert("UP");
break;
case tvKey.KEY_DOWN:
alert("DOWN");
break;
case tvKey.KEY_ENTER:
case tvKey.KEY_PANEL_ENTER:
alert("ENTER");
break;
default:
alert("Unhandled key");
break;
}
};
The registIMEKey method is part of the Plugin API.
var pluginAPI = new Common.API.Plugin();
pluginAPI.registIMEKey();
See: http://www.samsungdforum.com/Guide/ref00006/common_module_plugin_object.html#ref00006-common-module-plugin-object-registimekey
Edit: Updated to add code solution.
widgetAPI no contains method registIMEKey();, it contains in IMEShell.