feat: Add soft remove and recover methods to entity (#5854) · typeorm/typeorm@9d2b8e0
1+import "reflect-metadata";
2+import {expect} from "chai";
3+import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils";
4+import {Connection} from "../../../../src/connection/Connection";
5+import {Post} from "./entity/Post";
6+import { PostWithoutDeleteDateColumn } from "./entity/PostWithoutDeleteDateColumn";
7+import { MissingDeleteDateColumnError } from "../../../../src/error/MissingDeleteDateColumnError";
8+import { PromiseUtils } from "../../../../src";
9+10+describe("entity > soft-remove", () => {
11+12+let connections: Connection[];
13+before(async () => connections = await createTestingConnections({
14+entities: [__dirname + "/entity/*{.js,.ts}"],
15+}));
16+beforeEach(() => reloadTestingDatabases(connections));
17+after(() => closeTestingConnections(connections));
18+19+it("should perform soft removal and recovery correctly", () => PromiseUtils.runInSequence(connections, async connection => {
20+Post.useConnection(connection); // change connection each time because of AR specifics
21+22+const postRepository = connection.getRepository(Post);
23+24+// save a new posts
25+const newPost1 = postRepository.create({
26+id: 1,
27+name: "post#1"
28+});
29+const newPost2 = postRepository.create({
30+id: 2,
31+name: "post#2"
32+});
33+34+await postRepository.save(newPost1);
35+await postRepository.save(newPost2);
36+37+// soft-remove one
38+await newPost1.softRemove();
39+40+// load to check
41+const loadedPosts = await postRepository.find({ withDeleted: true });
42+43+// assert
44+loadedPosts.length.should.be.equal(2);
45+46+const loadedPost1 = loadedPosts.find(p => p.id === 1);
47+expect(loadedPost1).to.exist;
48+expect(loadedPost1!.deletedAt).to.be.instanceof(Date);
49+expect(loadedPost1!.name).to.equals("post#1");
50+const loadedPost2 = loadedPosts.find(p => p.id === 2);
51+expect(loadedPost2).to.exist;
52+expect(loadedPost2!.deletedAt).to.equals(null);
53+expect(loadedPost2!.name).to.equals("post#2");
54+55+// recover one
56+await loadedPost1!.recover();
57+// load to check
58+const recoveredPosts = await postRepository.find({ withDeleted: true });
59+60+// assert
61+recoveredPosts.length.should.be.equal(2);
62+63+const recoveredPost1 = recoveredPosts.find(p => p.id === 1);
64+expect(recoveredPost1).to.exist;
65+expect(recoveredPost1!.deletedAt).to.equals(null);
66+expect(recoveredPost1!.name).to.equals("post#1");
67+const recoveredPost2 = recoveredPosts.find(p => p.id === 2);
68+expect(recoveredPost2).to.exist;
69+expect(recoveredPost2!.deletedAt).to.equals(null);
70+expect(recoveredPost2!.name).to.equals("post#2");
71+72+}));
73+74+it("should throw error when delete date column is missing", () => PromiseUtils.runInSequence(connections, async connection => {
75+PostWithoutDeleteDateColumn.useConnection(connection); // change connection each time because of AR specifics
76+77+const postRepository = connection.getRepository(PostWithoutDeleteDateColumn);
78+79+// save a new posts
80+const newPost1 = postRepository.create({
81+id: 1,
82+name: "post#1"
83+});
84+85+await postRepository.save(newPost1);
86+87+let error1: Error | undefined;
88+try {
89+// soft-remove one
90+await newPost1.softRemove();
91+} catch (err) {
92+error1 = err;
93+}
94+expect(error1).to.be.an.instanceof(MissingDeleteDateColumnError);
95+96+let error2: Error | undefined;
97+try {
98+// recover one
99+await newPost1.recover();
100+} catch (err) {
101+error2 = err;
102+}
103+expect(error2).to.be.an.instanceof(MissingDeleteDateColumnError);
104+105+}));
106+});