Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
256 changes: 232 additions & 24 deletions src/sscce-sequelize-7.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,251 @@
import { CreationOptional, DataTypes, InferAttributes, InferCreationAttributes, Model } from '@sequelize/core';
import { Attribute, NotNull } from '@sequelize/core/decorators-legacy';
import { createSequelize7Instance } from '../dev/create-sequelize-instance';
import { expect } from 'chai';
import sinon from 'sinon';
import {
CreationOptional,
DataTypes,
InferAttributes,
InferCreationAttributes,
Model,
} from "@sequelize/core";
import { createSequelize7Instance } from "../dev/create-sequelize-instance";
import { expect } from "chai";

// if your issue is dialect specific, remove the dialects you don't need to test on.
export const testingOnDialects = new Set(['mssql', 'sqlite', 'mysql', 'mariadb', 'postgres', 'postgres-native']);
export const testingOnDialects = new Set(["postgres"]);

// You can delete this file if you don't want your SSCCE to be tested against Sequelize 7
class Location extends Model<
InferAttributes<Location>,
InferCreationAttributes<Location>
> {
declare id: CreationOptional<number>;
declare name: string;

declare customers?: Customer[];
declare systems?: System[];
}

class Customer extends Model<
InferAttributes<Customer>,
InferCreationAttributes<Customer>
> {
declare id: CreationOptional<number>;
declare name: string;

declare locations?: Location[];
}

class System extends Model<
InferAttributes<System>,
InferCreationAttributes<System>
> {
declare id: CreationOptional<number>;
declare name: string;
declare locationId: number;

declare location?: Location;
declare fuelDeliveries?: FuelDelivery[];
}

class FuelDelivery extends Model<
InferAttributes<FuelDelivery>,
InferCreationAttributes<FuelDelivery>
> {
declare id: CreationOptional<number>;
declare product: string;
declare systemId: number;

declare system?: System;
}

class LocationCustomer extends Model<
InferAttributes<LocationCustomer>,
InferCreationAttributes<LocationCustomer>
> {
declare locationId: number;
declare customerId: number;
}

// Your SSCCE goes inside this function.
export async function run() {
// This function should be used instead of `new Sequelize()`.
// It applies the config for your SSCCE to work on CI.
const sequelize = createSequelize7Instance({
logQueryParameters: true,
benchmark: true,
minifyAliases: true,
dialect: "postgres",
define: {
// For less clutter in the SSCCE
// Keep model definitions lean so the regression focus stays on include resolution.
timestamps: false,
},
});

class Foo extends Model<InferAttributes<Foo>, InferCreationAttributes<Foo>> {
declare id: CreationOptional<number>;
Location.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
},
{
sequelize,
tableName: "locations",
}
);

@Attribute(DataTypes.TEXT)
@NotNull
declare name: string;
}
Customer.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
},
{
sequelize,
tableName: "customers",
}
);

sequelize.addModels([Foo]);
System.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
name: {
type: DataTypes.STRING,
allowNull: false,
},
locationId: {
type: DataTypes.INTEGER,
allowNull: false,
},
},
{
sequelize,
tableName: "systems",
}
);

FuelDelivery.init(
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
product: {
type: DataTypes.STRING,
allowNull: false,
},
systemId: {
type: DataTypes.INTEGER,
allowNull: false,
},
},
{
sequelize,
tableName: "fuel_deliveries",
}
);

LocationCustomer.init(
{
locationId: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
},
customerId: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
},
},
{
sequelize,
tableName: "location_customers",
}
);

FuelDelivery.belongsTo(System, { as: "system", foreignKey: "systemId" });
System.hasMany(FuelDelivery, {
as: "fuelDeliveries",
foreignKey: "systemId",
});

// You can use sinon and chai assertions directly in your SSCCE.
const spy = sinon.spy();
sequelize.afterBulkSync(() => spy());
await sequelize.sync({ force: true });
expect(spy).to.have.been.called;
System.belongsTo(Location, { as: "location", foreignKey: "locationId" });
Location.hasMany(System, { as: "systems", foreignKey: "locationId" });

console.log(await Foo.create({ name: 'TS foo' }));
expect(await Foo.count()).to.equal(1);
Location.belongsToMany(Customer, {
as: "customers",
through: LocationCustomer,
foreignKey: "locationId",
otherKey: "customerId",
});
Customer.belongsToMany(Location, {
as: "locations",
through: LocationCustomer,
foreignKey: "customerId",
otherKey: "locationId",
});

try {
await sequelize.sync({ force: true });

const customer = await Customer.create({ name: "Propane Co-op" });
const location = await Location.create({ name: "Rural Depot" });
await LocationCustomer.create({
customerId: customer.id,
locationId: location.id,
});

const system = await System.create({
name: "Delivery System Alpha",
locationId: location.id,
});
const delivery = await FuelDelivery.create({
product: "Propane",
systemId: system.id,
});

const result = await FuelDelivery.findByPk(delivery.id, {
logging: console.log,
include: [
{
association: "system",
required: true,
include: [
{
association: "location",
required: true,
include: [
{
association: "customers",
required: true,
},
],
},
],
},
],
});

expect(result).to.not.be.null;
expect(result!.system).to.not.be.undefined;
expect(result!.system!.location).to.not.be.undefined;
const customers = result!.system!.location!.customers;
expect(customers).to.not.be.undefined;
expect(customers).to.have.length(1);
expect(customers![0].id).to.equal(customer.id);
} finally {
await sequelize.close();
}
}
Loading